pyocf: cache and core exported object volumes

Signed-off-by: Adam Rutkowski <adam.j.rutkowski@intel.com>
This commit is contained in:
Adam Rutkowski 2022-03-07 16:00:08 +01:00
parent d2164e4ffd
commit 9e88afad62
4 changed files with 161 additions and 0 deletions

View File

@ -0,0 +1,31 @@
#
# Copyright(c) 2022 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
#
from ctypes import cast, POINTER
from .cache import Cache
from .io import Io
from .io import IoDir
from .volume_exp_obj import ExpObjVolume
from .volume import Volume
class CacheVolume(ExpObjVolume):
def __init__(self, cache, open=False, uuid=None):
super().__init__(cache, uuid)
self.cache = cache
self.lib = cache.owner.lib
if open:
self.open()
def md5(self):
data = self._read()
return data.md5()
def open(self):
return Volume.open(
self.lib.ocf_cache_get_front_volume(self.cache.handle),
self
)

View File

@ -0,0 +1,27 @@
#
# Copyright(c) 2022 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
#
from .core import Core
from .volume_exp_obj import ExpObjVolume
from .io import IoDir
from .volume import Volume
class CoreVolume(ExpObjVolume):
def __init__(self, core, open=False, uuid=None):
super().__init__(core, uuid)
self.core = core
self.lib = core.cache.owner.lib
if open:
self.open()
def md5(self):
return self.core.exp_obj_md5()
def open(self):
return Volume.open(
self.lib.ocf_core_get_front_volume(self.core.handle),
self
)

View File

@ -0,0 +1,97 @@
#
# Copyright(c) 2022 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
#
from ctypes import c_int, c_void_p, CFUNCTYPE, byref, c_uint32, c_uint64, cast, POINTER
from ..ocf import OcfLib
from .volume import Volume, VOLUME_POISON
from pyocf.utils import Size
from pyocf.types.data import Data
from pyocf.types.io import IoDir, Io
from pyocf.types.shared import OcfCompletion
class ExpObjVolume(Volume):
def __init__(self, parent, uuid=None):
super().__init__(uuid)
self.parent = parent
def __alloc_io(self, addr, _bytes, _dir, _class, _flags):
vol = self.parent.get_front_volume()
queue = self.parent.get_default_queue() # TODO multiple queues?
return vol.new_io(
queue, addr, _bytes, _dir, _class, _flags
)
def _alloc_io(self, io):
exp_obj_io = self.__alloc_io(
io.contents._addr,
io.contents._bytes,
io.contents._dir,
io.contents._class,
io.contents._flags,
)
lib = OcfLib.getInstance()
cdata = OcfLib.getInstance().ocf_io_get_data(io)
OcfLib.getInstance().ocf_io_set_data(byref(exp_obj_io), cdata, 0)
def cb(error):
nonlocal io
io = cast(io, POINTER(Io))
io.contents._end(io, error)
exp_obj_io.callback = cb
return exp_obj_io
def get_length(self):
return Size.from_B(OcfLib.getInstance().ocf_volume_get_length(self.c_vol))
def get_max_io_size(self):
return Size.from_B(OcfLib.getInstance().ocf_volume_get_max_io_size(self.c_vol))
def do_submit_io(self, io):
io = self._alloc_io(io)
io.submit()
def do_submit_flush(self, flush):
io = self._alloc_io(flush)
io.submit_flush()
def do_submit_discard(self, discard):
io = self._alloc_io(discard)
io.submit_discard()
def _read(self, offset=0, size=0):
if size == 0:
size = self.get_length().B - offset
exp_obj_io = self.__alloc_io(offset, size, IoDir.READ, 0, 0)
completion = OcfCompletion([("err", c_int)])
exp_obj_io.callback = completion
data = Data.from_bytes(bytes(size))
exp_obj_io.set_data(data)
exp_obj_io.submit()
completion.wait()
error = completion.results["err"]
if error:
raise Exception("error reading exported object for dump")
return data
def dump(self, offset=0, size=0, ignore=VOLUME_POISON, **kwargs):
data = self._read(offset, size)
data.dump(ignore=ifnore, **kwargs)
def md5(self):
raise NotImplementedError
lib = OcfLib.getInstance()
lib.ocf_volume_get_max_io_size.argtypes = [c_void_p]
lib.ocf_volume_get_max_io_size.restype = c_uint32
lib.ocf_volume_get_length.argtypes = [c_void_p]
lib.ocf_volume_get_length.restype = c_uint64
lib.ocf_io_get_data.argtypes = [POINTER(Io)]
lib.ocf_io_get_data.restype = c_void_p

View File

@ -11,6 +11,8 @@ import gc
sys.path.append(os.path.join(os.path.dirname(__file__), os.path.pardir)) sys.path.append(os.path.join(os.path.dirname(__file__), os.path.pardir))
from pyocf.types.logger import LogLevel, DefaultLogger, BufferLogger from pyocf.types.logger import LogLevel, DefaultLogger, BufferLogger
from pyocf.types.volume import RamVolume, ErrorDevice from pyocf.types.volume import RamVolume, ErrorDevice
from pyocf.types.volume_cache import CacheVolume
from pyocf.types.volume_core import CoreVolume
from pyocf.types.volume_replicated import ReplicatedVolume from pyocf.types.volume_replicated import ReplicatedVolume
from pyocf.types.ctx import OcfCtx from pyocf.types.ctx import OcfCtx
@ -24,6 +26,8 @@ def pyocf_ctx():
c = OcfCtx.with_defaults(DefaultLogger(LogLevel.WARN)) c = OcfCtx.with_defaults(DefaultLogger(LogLevel.WARN))
c.register_volume_type(RamVolume) c.register_volume_type(RamVolume)
c.register_volume_type(ErrorDevice) c.register_volume_type(ErrorDevice)
c.register_volume_type(CacheVolume)
c.register_volume_type(CoreVolume)
c.register_volume_type(ReplicatedVolume) c.register_volume_type(ReplicatedVolume)
yield c yield c
c.exit() c.exit()
@ -36,6 +40,8 @@ def pyocf_ctx_log_buffer():
c = OcfCtx.with_defaults(logger) c = OcfCtx.with_defaults(logger)
c.register_volume_type(RamVolume) c.register_volume_type(RamVolume)
c.register_volume_type(ErrorDevice) c.register_volume_type(ErrorDevice)
c.register_volume_type(CacheVolume)
c.register_volume_type(CoreVolume)
c.register_volume_type(ReplicatedVolume) c.register_volume_type(ReplicatedVolume)
yield logger yield logger
c.exit() c.exit()