
Change license to BSD-3-Clause Signed-off-by: Rafal Stefanowski <rafal.stefanowski@intel.com>
282 lines
5.1 KiB
C
282 lines
5.1 KiB
C
/*
|
|
* Copyright(c) 2012-2021 Intel Corporation
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "vol_blk_utils.h"
|
|
|
|
static void cas_io_iter_advanced(struct bio_vec_iter *iter, uint32_t bytes)
|
|
{
|
|
BUG_ON(bytes > iter->len);
|
|
|
|
iter->len -= bytes;
|
|
iter->offset += bytes;
|
|
|
|
if (iter->len) {
|
|
/* Still in this item, bytes to be processed */
|
|
return;
|
|
}
|
|
|
|
/* Move to next item in data vector */
|
|
iter->idx++;
|
|
if (iter->idx < iter->vec_size) {
|
|
iter->ivec = &iter->vec[iter->idx];
|
|
iter->len = iter->ivec->bv_len;
|
|
iter->offset = iter->ivec->bv_offset;
|
|
} else {
|
|
iter->ivec = NULL;
|
|
iter->len = 0;
|
|
iter->offset = 0;
|
|
}
|
|
}
|
|
|
|
uint32_t cas_io_iter_cpy(struct bio_vec_iter *dst, struct bio_vec_iter *src,
|
|
uint32_t bytes)
|
|
{
|
|
uint32_t to_copy, written = 0;
|
|
void *adst, *asrc;
|
|
|
|
if (dst->idx >= dst->vec_size)
|
|
return 0;
|
|
|
|
BUG_ON(dst->offset + dst->len > PAGE_SIZE);
|
|
|
|
if (src->idx >= src->vec_size)
|
|
return 0;
|
|
|
|
BUG_ON(src->offset + src->len > PAGE_SIZE);
|
|
|
|
while (bytes) {
|
|
to_copy = min(dst->len, src->len);
|
|
to_copy = min(to_copy, bytes);
|
|
if (to_copy == 0) {
|
|
/* No more bytes for coping */
|
|
break;
|
|
}
|
|
|
|
adst = page_address(dst->ivec->bv_page) + dst->offset;
|
|
asrc = page_address(src->ivec->bv_page) + src->offset;
|
|
|
|
memcpy(adst, asrc, to_copy);
|
|
|
|
bytes -= to_copy;
|
|
written += to_copy;
|
|
|
|
cas_io_iter_advanced(dst, to_copy);
|
|
cas_io_iter_advanced(src, to_copy);
|
|
}
|
|
|
|
return written;
|
|
}
|
|
|
|
uint32_t cas_io_iter_cpy_from_data(struct bio_vec_iter *dst,
|
|
const void *src, uint32_t bytes)
|
|
{
|
|
uint32_t to_copy, written = 0;
|
|
void *adst;
|
|
const void *asrc;
|
|
|
|
if (dst->idx >= dst->vec_size)
|
|
return 0;
|
|
|
|
BUG_ON(dst->offset + dst->len > PAGE_SIZE);
|
|
|
|
while (bytes) {
|
|
to_copy = min(dst->len, bytes);
|
|
if (to_copy == 0) {
|
|
/* No more bytes for coping */
|
|
break;
|
|
}
|
|
|
|
adst = page_address(dst->ivec->bv_page) + dst->offset;
|
|
asrc = src + written;
|
|
|
|
memcpy(adst, asrc, to_copy);
|
|
|
|
bytes -= to_copy;
|
|
written += to_copy;
|
|
|
|
cas_io_iter_advanced(dst, to_copy);
|
|
}
|
|
|
|
return written;
|
|
}
|
|
|
|
uint32_t cas_io_iter_cpy_to_data(void *dst, struct bio_vec_iter *src,
|
|
uint32_t bytes)
|
|
{
|
|
uint32_t to_copy, written = 0;
|
|
void *adst, *asrc;
|
|
|
|
BUG_ON(dst == NULL);
|
|
|
|
if (src->idx >= src->vec_size)
|
|
return 0;
|
|
|
|
BUG_ON(src->offset + src->len > PAGE_SIZE);
|
|
|
|
while (bytes) {
|
|
to_copy = min(bytes, src->len);
|
|
if (to_copy == 0) {
|
|
/* No more bytes for coping */
|
|
break;
|
|
}
|
|
|
|
adst = dst + written;
|
|
asrc = page_address(src->ivec->bv_page) + src->offset;
|
|
|
|
memcpy(adst, asrc, to_copy);
|
|
|
|
bytes -= to_copy;
|
|
written += to_copy;
|
|
|
|
cas_io_iter_advanced(src, to_copy);
|
|
}
|
|
|
|
return written;
|
|
}
|
|
|
|
uint32_t cas_io_iter_move(struct bio_vec_iter *iter, uint32_t bytes)
|
|
{
|
|
uint32_t to_move, moved = 0;
|
|
|
|
if (iter->idx >= iter->vec_size)
|
|
return 0;
|
|
|
|
BUG_ON(iter->offset + iter->len > PAGE_SIZE);
|
|
|
|
while (bytes) {
|
|
to_move = min(iter->len, bytes);
|
|
if (to_move == 0) {
|
|
/* No more bytes for coping */
|
|
break;
|
|
}
|
|
|
|
bytes -= to_move;
|
|
moved += to_move;
|
|
|
|
cas_io_iter_advanced(iter, to_move);
|
|
}
|
|
|
|
return moved;
|
|
}
|
|
|
|
uint32_t cas_io_iter_zero(struct bio_vec_iter *dst, uint32_t bytes)
|
|
{
|
|
uint32_t to_fill, zeroed = 0;
|
|
void *adst;
|
|
|
|
if (dst->idx >= dst->vec_size)
|
|
return 0;
|
|
|
|
BUG_ON(dst->offset + dst->len > PAGE_SIZE);
|
|
|
|
while (bytes) {
|
|
to_fill = min(dst->len, (typeof(dst->len))PAGE_SIZE);
|
|
if (to_fill == 0) {
|
|
/* No more bytes for coping */
|
|
break;
|
|
}
|
|
|
|
adst = page_address(dst->ivec->bv_page) + dst->offset;
|
|
|
|
memset(adst, 0, to_fill);
|
|
|
|
bytes -= to_fill;
|
|
zeroed += to_fill;
|
|
|
|
cas_io_iter_advanced(dst, to_fill);
|
|
}
|
|
|
|
return zeroed;
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
int cas_blk_io_set_data(struct ocf_io *io,
|
|
ctx_data_t *ctx_data, uint32_t offset)
|
|
{
|
|
struct blkio *blkio = cas_io_to_blkio(io);
|
|
struct blk_data *data = ctx_data;
|
|
|
|
/* Set BIO vector (IO data) and initialize iterator */
|
|
blkio->data = data;
|
|
if (blkio->data) {
|
|
cas_io_iter_init(&blkio->iter, blkio->data->vec,
|
|
blkio->data->size);
|
|
|
|
/* Move into specified offset in BIO vector iterator */
|
|
if (offset != cas_io_iter_move(&blkio->iter, offset)) {
|
|
/* TODO Log message */
|
|
blkio->error = -ENOBUFS;
|
|
return -ENOBUFS;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
ctx_data_t *cas_blk_io_get_data(struct ocf_io *io)
|
|
{
|
|
struct blkio *blkio = cas_io_to_blkio(io);
|
|
|
|
return blkio->data;
|
|
}
|
|
|
|
int cas_blk_open_volume_by_bdev(ocf_volume_t *vol, struct block_device *bdev)
|
|
{
|
|
struct bd_object *bdobj;
|
|
int ret;
|
|
|
|
ret = ocf_ctx_volume_create(cas_ctx, vol, NULL, BLOCK_DEVICE_VOLUME);
|
|
if (ret)
|
|
goto err;
|
|
|
|
bdobj = bd_object(*vol);
|
|
|
|
bdobj->btm_bd = bdev;
|
|
bdobj->opened_by_bdev = true;
|
|
|
|
return ocf_volume_open(*vol, NULL);
|
|
|
|
err:
|
|
return ret;
|
|
}
|
|
|
|
void cas_blk_close_volume(ocf_volume_t vol)
|
|
{
|
|
ocf_volume_close(vol);
|
|
ocf_volume_deinit(vol);
|
|
env_free(vol);
|
|
}
|
|
|
|
int _cas_blk_identify_type(const char *path, uint8_t *type)
|
|
{
|
|
struct file *file;
|
|
int result = 0;
|
|
|
|
file = filp_open(path, O_RDONLY, 0);
|
|
if (IS_ERR(file))
|
|
return -OCF_ERR_INVAL_VOLUME_TYPE;
|
|
|
|
if (S_ISBLK(CAS_FILE_INODE(file)->i_mode))
|
|
*type = BLOCK_DEVICE_VOLUME;
|
|
else
|
|
result = -OCF_ERR_INVAL_VOLUME_TYPE;
|
|
|
|
filp_close(file, 0);
|
|
if (result)
|
|
return result;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int cas_blk_identify_type(const char *path, uint8_t *type)
|
|
{
|
|
return _cas_blk_identify_type(path, type);
|
|
}
|