Merge pull request #634 from arutk/mopft_21.12

pyocf: management operation power failure tests
This commit is contained in:
Robert Baldyga
2022-02-14 14:10:52 +01:00
committed by GitHub
9 changed files with 811 additions and 26 deletions

View File

@@ -75,6 +75,7 @@ class CacheAttachConfig(Structure):
("_open_cores", c_bool),
("_force", c_bool),
("_discard_on_start", c_bool),
("_volume_params", c_void_p),
]
@@ -348,6 +349,7 @@ class Cache:
raise OcfError("Error retriving ioclass info", status)
return {
"_class_id": part_id,
"_name": ioclass_info._name.decode("ascii"),
"_cache_mode": ioclass_info._cache_mode,
"_priority": int(ioclass_info._priority),
@@ -402,7 +404,7 @@ class Cache:
ioclasses_info._config[i]._name = (
ioclass_info._name if len(ioclass_info._name) > 0 else 0
)
ioclasses_info._config[i]._prio = ioclass_info._priority
ioclasses_info._config[i]._priority = ioclass_info._priority
ioclasses_info._config[i]._cache_mode = ioclass_info._cache_mode
ioclasses_info._config[i]._max_size = ioclass_info._max_size
@@ -410,7 +412,7 @@ class Cache:
ioclasses_info._config[part_id]._name = name.encode("utf-8")
ioclasses_info._config[part_id]._cache_mode = int(cache_mode)
ioclasses_info._config[part_id]._prio = priority
ioclasses_info._config[part_id]._priority = priority
ioclasses_info._config[part_id]._max_size = max_size
self.write_lock()
@@ -425,7 +427,12 @@ class Cache:
raise OcfError("Error adding partition to cache", status)
def configure_device(
self, device, force=False, perform_test=True, cache_line_size=None
self,
device,
force=False,
perform_test=True,
cache_line_size=None,
open_cores=True,
):
self.device = device
self.device_name = device.uuid
@@ -447,15 +454,22 @@ class Cache:
_cache_line_size=cache_line_size
if cache_line_size
else self.cache_line_size,
_open_cores=open_cores,
_force=force,
_open_cores=True,
_discard_on_start=False,
)
def attach_device(
self, device, force=False, perform_test=False, cache_line_size=None
self,
device,
force=False,
perform_test=False,
cache_line_size=None,
open_cores=True,
):
self.configure_device(device, force, perform_test, cache_line_size)
self.configure_device(
device, force, perform_test, cache_line_size, open_cores=open_cores
)
self.write_lock()
c = OcfCompletion([("cache", c_void_p), ("priv", c_void_p), ("error", c_int)])
@@ -483,8 +497,8 @@ class Cache:
if c.results["error"]:
raise OcfError("Attaching cache device failed", c.results["error"])
def load_cache(self, device):
self.configure_device(device)
def load_cache(self, device, open_cores=True):
self.configure_device(device, open_cores=open_cores)
c = OcfCompletion([("cache", c_void_p), ("priv", c_void_p), ("error", c_int)])
device.owner.lib.ocf_mngt_cache_load(
self.cache_handle, byref(self.dev_cfg), c, None
@@ -495,12 +509,12 @@ class Cache:
raise OcfError("Loading cache device failed", c.results["error"])
@classmethod
def load_from_device(cls, device, name="cache"):
def load_from_device(cls, device, name="cache", open_cores=True):
c = cls(name=name, owner=device.owner)
c.start_cache()
try:
c.load_cache(device)
c.load_cache(device, open_cores=open_cores)
except: # noqa E722
c.stop()
raise
@@ -686,7 +700,8 @@ class Cache:
self.owner.lib.ocf_mngt_cache_stop(self.cache_handle, c, None)
c.wait()
if c.results["error"]:
err = OcfErrorCode(-1 * c.results["error"])
if err != OcfErrorCode.OCF_OK and err != OcfErrorCode.OCF_ERR_WRITE_CACHE:
self.write_unlock()
raise OcfError("Failed stopping cache", c.results["error"])
@@ -698,6 +713,9 @@ class Cache:
self.owner.caches.remove(self)
if err != OcfErrorCode.OCF_OK:
raise OcfError("Failed stopping cache", c.results["error"])
def flush(self):
self.write_lock()

View File

@@ -97,6 +97,7 @@ class OcfCtx:
self.cleaner = None
Queue._instances_ = {}
Volume._instances_ = {}
Volume._uuid_ = {}
Data._instances_ = {}
Logger._instances_ = {}

View File

@@ -223,3 +223,6 @@ class Data:
m = md5()
m.update(string_at(self.handle, self.size))
return m.hexdigest()
def get_bytes(self):
return string_at(self.handle, self.size)

View File

@@ -25,7 +25,7 @@ class IoClassConfig(Structure):
("_max_size", c_uint32),
("_name", c_char_p),
("_cache_mode", c_int),
("_prio", c_uint16),
("_priority", c_uint16),
]

View File

@@ -12,6 +12,7 @@ from ..utils import Size as S
class OcfErrorCode(IntEnum):
OCF_OK = 0
OCF_ERR_INVAL = 1000000
OCF_ERR_AGAIN = auto()
OCF_ERR_INTR = auto()

View File

@@ -203,7 +203,7 @@ class Volume(Structure):
return -1
if volume.opened:
return OcfErrorCode.OCF_ERR_NOT_OPEN_EXC
return -OcfErrorCode.OCF_ERR_NOT_OPEN_EXC
Volume._instances_[ref] = weakref.ref(volume)
@@ -275,7 +275,7 @@ class Volume(Structure):
discard.contents._end(discard, 0)
except: # noqa E722
discard.contents._end(discard, -5)
discard.contents._end(discard, -OcfErrorCode.OCF_ERR_NOT_SUPP)
def get_stats(self):
return self.stats
@@ -305,40 +305,80 @@ class Volume(Structure):
io.contents._end(io, 0)
except: # noqa E722
io.contents._end(io, -5)
io.contents._end(io, -OcfErrorCode.OCF_ERR_IO)
def dump(self, offset=0, size=0, ignore=VOLUME_POISON, **kwargs):
if size == 0:
size = int(self.size) - int(offset)
print_buffer(
self._storage,
size,
ignore=ignore,
**kwargs
)
print_buffer(self._storage, size, ignore=ignore, **kwargs)
def md5(self):
m = md5()
m.update(string_at(self._storage, self.size))
return m.hexdigest()
def get_bytes(self):
return string_at(self._storage, self.size)
class ErrorDevice(Volume):
def __init__(self, size, error_sectors: set = None, uuid=None):
def __init__(
self,
size,
error_sectors: set = None,
error_seq_no: dict = None,
armed=True,
uuid=None,
):
super().__init__(size, uuid)
self.error_sectors = error_sectors or set()
self.error_sectors = error_sectors
self.error_seq_no = error_seq_no
self.armed = armed
self.io_seq_no = {IoDir.WRITE: 0, IoDir.READ: 0}
self.error = False
def set_mapping(self, error_sectors: set):
self.error_sectors = error_sectors
def submit_io(self, io):
if io.contents._addr in self.error_sectors:
io.contents._end(io, -5)
self.stats["errors"][io.contents._dir] += 1
if not self.armed:
super().submit_io(io)
return
direction = IoDir(io.contents._dir)
seq_no_match = (
self.error_seq_no is not None
and direction in self.error_seq_no
and self.error_seq_no[direction] <= self.io_seq_no[direction]
)
sector_match = (
self.error_sectors is not None and io.contents._addr in self.error_sectors
)
self.io_seq_no[direction] += 1
error = True
if self.error_seq_no is not None and not seq_no_match:
error = False
if self.error_sectors is not None and not sector_match:
error = False
if error:
self.error = True
io.contents._end(io, -OcfErrorCode.OCF_ERR_IO)
self.stats["errors"][direction] += 1
else:
super().submit_io(io)
def arm(self):
self.armed = True
def disarm(self):
self.armed = False
def error_triggered(self):
return self.error
def reset_stats(self):
super().reset_stats()
self.stats["errors"] = {IoDir.WRITE: 0, IoDir.READ: 0}

View File

@@ -0,0 +1,14 @@
/*
* Copyright(c) 2021-2022 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "ocf/ocf_io.h"
#include "ocf/ocf_core.h"
const struct ocf_volume_uuid *ocf_core_get_uuid_wrapper(ocf_core_t core)
{
return ocf_core_get_uuid(core);
}