diff --git a/src/ocf_composite_volume.c b/src/ocf_composite_volume.c index 9ef5fc9..717ca97 100644 --- a/src/ocf_composite_volume.c +++ b/src/ocf_composite_volume.c @@ -199,6 +199,51 @@ void ocf_composite_forward_discard(ocf_volume_t cvolume, ocf_forward_end(token, 0); } +void ocf_composite_forward_write_zeros(ocf_volume_t cvolume, + ocf_forward_token_t token, uint64_t addr, uint64_t bytes) +{ + struct ocf_composite_volume *composite = ocf_volume_get_priv(cvolume); + uint64_t member_bytes, caddr; + int i; + + caddr = addr; + + ENV_BUG_ON(addr >= composite->length); + ENV_BUG_ON(addr + bytes > composite->length); + + for (i = 0; i < composite->members_cnt; i++) { + if (addr >= composite->end_addr[i]) + continue; + + if (unlikely(!composite->member[i].volume.opened)) { + ocf_forward_end(token, -OCF_ERR_INVAL); + return; + } + + addr = addr - (i > 0 ? composite->end_addr[i-1] : 0); + break; + } + + for (; i < composite->members_cnt && bytes; i++) { + if (unlikely(!composite->member[i].volume.opened)) { + ocf_forward_end(token, -OCF_ERR_INVAL); + return; + } + + member_bytes = OCF_MIN(bytes, composite->end_addr[i] - caddr); + + ocf_forward_write_zeros(&composite->member[i].volume, token, + addr, member_bytes); + + addr = 0; + caddr = composite->end_addr[i]; + bytes -= member_bytes; + } + + /* Put io forward counter to account for the original forward */ + ocf_forward_end(token, 0); +} + /* *** VOLUME OPS *** */ static int ocf_composite_volume_open(ocf_volume_t cvolume, void *volume_params) @@ -320,6 +365,7 @@ const struct ocf_volume_properties ocf_composite_volume_properties = { .forward_io = ocf_composite_forward_io, .forward_flush = ocf_composite_forward_flush, .forward_discard = ocf_composite_forward_discard, + .forward_write_zeros = ocf_composite_forward_write_zeros, .open = ocf_composite_volume_open, .close = ocf_composite_volume_close,