diff --git a/inc/ocf_io.h b/inc/ocf_io.h index 467eaa9..95403e9 100644 --- a/inc/ocf_io.h +++ b/inc/ocf_io.h @@ -299,6 +299,23 @@ void ocf_forward_discard(ocf_volume_t volume, ocf_forward_token_t token, void ocf_forward_write_zeros(ocf_volume_t volume, ocf_forward_token_t token, uint64_t addr, uint64_t bytes); +/** + * @brief Forward metadata io to another subvolume + * + * Forwarding automatically increases forwarded io refcount, so at some + * point additional ocf_forward_end() needs to be called to balance it. + * + * @param[in] token Forward token + * @param[in] volume Volume to which IO is being submitted + * @param[in] token Token representing IO to be forwarded + * @param[in] dir Direction OCF_READ/OCF_WRITE + * @param[in] addr Address to which IO is being submitted + * @param[in] bytes Length of the IO + * @param[in] offset Offset within the IO data + */ +void ocf_forward_metadata(ocf_volume_t volume, ocf_forward_token_t token, + int dir, uint64_t addr, uint64_t bytes, uint64_t offset); + /** * @brief Increment forwarded io refcount * diff --git a/inc/ocf_volume.h b/inc/ocf_volume.h index 85f8d9b..d3491e2 100644 --- a/inc/ocf_volume.h +++ b/inc/ocf_volume.h @@ -129,6 +129,20 @@ struct ocf_volume_ops { ocf_forward_token_t token, uint64_t addr, uint64_t bytes); + /** + * @brief Forward the metadata io directly to the volume + * + * @param[in] volume Volume to which IO is being submitted + * @param[in] token Token representing IO to be forwarded + * @param[in] dir Direction OCF_READ/OCF_WRITE + * @param[in] addr Address to which IO is being submitted + * @param[in] bytes Length of the IO + * @param[in] offset Offset within the IO data + */ + void (*forward_metadata)(ocf_volume_t volume, ocf_forward_token_t token, + int dir, uint64_t addr, uint64_t bytes, + uint64_t offset); + /** * @brief Volume initialization callback, called when volume object * is being initialized diff --git a/src/ocf_request.c b/src/ocf_request.c index 0b8a7be..f66ad85 100644 --- a/src/ocf_request.c +++ b/src/ocf_request.c @@ -479,6 +479,18 @@ void ocf_req_forward_cache_write_zeros(struct ocf_request *req, uint64_t addr, ocf_volume_forward_write_zeros(volume, token, addr, bytes); } +void ocf_req_forward_cache_metadata(struct ocf_request *req, int dir, + uint64_t addr, uint64_t bytes, uint64_t offset) +{ + ocf_volume_t volume = ocf_cache_get_volume(req->cache); + ocf_forward_token_t token = ocf_req_to_cache_forward_token(req); + + req->cache_error = 0; + + ocf_req_forward_cache_get(req); + ocf_volume_forward_metadata(volume, token, dir, addr, bytes, offset); +} + void ocf_req_forward_core_io(struct ocf_request *req, int dir, uint64_t addr, uint64_t bytes, uint64_t offset) { @@ -563,6 +575,13 @@ void ocf_forward_write_zeros(ocf_volume_t volume, ocf_forward_token_t token, ocf_volume_forward_write_zeros(volume, token, addr, bytes); } +void ocf_forward_metadata(ocf_volume_t volume, ocf_forward_token_t token, + int dir, uint64_t addr, uint64_t bytes, uint64_t offset) +{ + _ocf_forward_get(token); + ocf_volume_forward_metadata(volume, token, dir, addr, bytes, offset); +} + void ocf_forward_end(ocf_forward_token_t token, int error) { struct ocf_request *req = ocf_req_forward_token_to_req(token); diff --git a/src/ocf_request.h b/src/ocf_request.h index a3ad3d7..96c6908 100644 --- a/src/ocf_request.h +++ b/src/ocf_request.h @@ -564,6 +564,9 @@ void ocf_req_forward_cache_discard(struct ocf_request *req, uint64_t addr, void ocf_req_forward_cache_write_zeros(struct ocf_request *req, uint64_t addr, uint64_t bytes); +void ocf_req_forward_cache_metadata(struct ocf_request *req, int dir, + uint64_t addr, uint64_t bytes, uint64_t offset); + void ocf_req_forward_core_io(struct ocf_request *req, int dir, uint64_t addr, uint64_t bytes, uint64_t offset); diff --git a/src/ocf_volume.c b/src/ocf_volume.c index 2ec2890..6833a49 100644 --- a/src/ocf_volume.c +++ b/src/ocf_volume.c @@ -384,6 +384,20 @@ void ocf_volume_forward_write_zeros(ocf_volume_t volume, addr, bytes); } +void ocf_volume_forward_metadata(ocf_volume_t volume, ocf_forward_token_t token, + int dir, uint64_t addr, uint64_t bytes, uint64_t offset) +{ + ENV_BUG_ON(!volume->type->properties->ops.forward_metadata); + + if (!volume->opened) { + ocf_forward_end(token, -OCF_ERR_IO); + return; + } + + volume->type->properties->ops.forward_metadata(volume, token, + dir, addr, bytes, offset); +} + int ocf_volume_open(ocf_volume_t volume, void *volume_params) { int ret; diff --git a/src/ocf_volume_priv.h b/src/ocf_volume_priv.h index 4b730fc..3b31f39 100644 --- a/src/ocf_volume_priv.h +++ b/src/ocf_volume_priv.h @@ -58,6 +58,9 @@ void ocf_volume_forward_discard(ocf_volume_t volume, ocf_forward_token_t token, void ocf_volume_forward_write_zeros(ocf_volume_t volume, ocf_forward_token_t token, uint64_t addr, uint64_t bytes); +void ocf_volume_forward_metadata(ocf_volume_t volume, ocf_forward_token_t token, + int dir, uint64_t addr, uint64_t bytes, uint64_t offset); + static inline void ocf_volume_submit_metadata(struct ocf_io *io) { ocf_volume_t volume = ocf_io_get_volume(io); diff --git a/tests/functional/pyocf/types/volume.py b/tests/functional/pyocf/types/volume.py index 4f6badb..9ef3082 100644 --- a/tests/functional/pyocf/types/volume.py +++ b/tests/functional/pyocf/types/volume.py @@ -55,6 +55,7 @@ class VolumeOps(Structure): FORWARD_FLUSH = CFUNCTYPE(None, c_void_p, c_uint64) FORWARD_DISCARD = CFUNCTYPE(None, c_void_p, c_uint64, c_uint64, c_uint64) FORWARD_WRITE_ZEROS = CFUNCTYPE(None, c_void_p, c_uint64, c_uint64, c_uint64) + FORWARD_METADATA = CFUNCTYPE(None, c_void_p, c_uint64, c_int, c_uint64, c_uint64, c_uint64) ON_INIT = CFUNCTYPE(c_int, c_void_p) ON_DEINIT = CFUNCTYPE(None, c_void_p) OPEN = CFUNCTYPE(c_int, c_void_p, c_void_p) @@ -72,6 +73,7 @@ class VolumeOps(Structure): ("_forward_flush", FORWARD_FLUSH), ("_forward_discard", FORWARD_DISCARD), ("_forward_write_zeros", FORWARD_WRITE_ZEROS), + ("_forward_metadata", FORWARD_METADATA), ("_on_init", ON_INIT), ("_on_deinit", ON_DEINIT), ("_open", OPEN),