/*---------------------------------------------------------------------------*/ int xio_validate_rdma_op(struct xio_vmsg *vmsg, struct xio_sge *rsg_list, size_t rsize, int max_sge, int op_size, int *tasks_used) { struct sg_table *sgtbl; struct scatterlist *liov; uint64_t raddr; uint32_t rlen; uint64_t laddr; uint32_t llen; uint32_t tot_len = 0; size_t lsize, lnents; int l, r; int k = 0; if (rsize < 1) { ERROR_LOG("rsize:%zu\n", rsize); *tasks_used = 0; return -1; } sgtbl = &vmsg->data_tbl; lnents = sgtbl->nents; if (lnents > XIO_MAX_IOV || lnents == 0) { WARN_LOG("IOV size %zu\n", lnents); *tasks_used = 0; return -EINVAL; } lsize = lnents; liov = sgtbl->sgl; r = 0; rlen = rsg_list[r].length; raddr = rsg_list[r].addr; l = 0; laddr = uint64_from_ptr(sg_virt(liov)); llen = liov->length; /* At least one task */ *tasks_used = 1; while (1) { if (rlen < llen) { r++; tot_len += rlen; if (r == rsize) break; llen -= rlen; laddr += rlen; raddr = rsg_list[r].addr; rlen = rsg_list[r].length; (*tasks_used)++; k = 0; } else if (llen < rlen) { /* check page alignment when source buff spans more * then one destination buffer */ l++; tot_len += llen; if (l == lsize) break; k++; if (k == max_sge - 1) { /* reached last index */ (*tasks_used)++; k = 0; } rlen -= llen; raddr += llen; laddr = uint64_from_ptr(sg_virt(liov)); llen = liov->length; } else { l++; r++; tot_len += llen; if ((l == lsize) || (r == rsize)) break; laddr = uint64_from_ptr(sg_virt(liov)); llen = liov->length; raddr = rsg_list[r].addr; rlen = rsg_list[r].length; (*tasks_used)++; k = 0; } } /* not enough buffers to complete */ if (tot_len < op_size) { *tasks_used = 0; ERROR_LOG("iovec exhausted\n"); return -1; } return 0; }
int xio_validate_rdma_op(struct xio_vmsg *vmsg, struct xio_sge *rsg_list, size_t rsize, int op_size) { struct xio_iovec_ex *liov; uint64_t raddr; uint32_t rlen; uint64_t laddr; uint32_t llen; uint32_t tot_len = 0; size_t lsize; int l, r; if (rsize < 1) { ERROR_LOG("rsize:%zu\n", rsize); return -1; } if (vmsg->data_iovlen > XIO_MAX_IOV || vmsg->data_iovlen == 0) { WARN_LOG("IOV size %zu\n", vmsg->data_iovlen); return -EINVAL; } lsize = vmsg->data_iovlen; liov = vmsg->data_iov; r = 0; rlen = rsg_list[r].length; raddr = rsg_list[r].addr; l = 0; laddr = uint64_from_ptr(liov[l].iov_base); llen = liov[l].iov_len; while (1) { if (rlen < llen) { r++; tot_len += rlen; if (r == rsize) break; llen -= rlen; laddr += rlen; raddr = rsg_list[r].addr; rlen = rsg_list[r].length; } else if (llen < rlen) { /* check page alignment when source buff spans more * then one destination buffer */ l++; tot_len += llen; if (l == lsize) break; rlen -= llen; raddr += llen; laddr = uint64_from_ptr(liov[l].iov_base); llen = liov[l].iov_len; } else { l++; r++; tot_len += llen; if ((l == lsize) || (r == rsize)) break; laddr = uint64_from_ptr(liov[l].iov_base); llen = liov[l].iov_len; raddr = rsg_list[r].addr; rlen = rsg_list[r].length; } } /* not enough buffers to complete */ if (tot_len < op_size) { ERROR_LOG("iovec exausted\n"); return -1; } return 0; }