mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-19 08:36:49 +00:00
lxip: fix iovec iter operations
This commit is contained in:
parent
028aeafabe
commit
5b6735e1c9
@ -535,60 +535,61 @@ extern "C" void lx_trace_event(char const *fmt, ...)
|
||||
** linux/uio.h **
|
||||
*****************/
|
||||
|
||||
size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
|
||||
static inline size_t _copy_iter(void *addr, size_t bytes,
|
||||
struct iov_iter *i, bool to_iter)
|
||||
{
|
||||
if (bytes > i->count)
|
||||
bytes = i->count;
|
||||
if (addr == nullptr) { return 0; }
|
||||
|
||||
if (bytes == 0)
|
||||
if (i->count == 0 ||
|
||||
i->iov == nullptr ||
|
||||
i->iov->iov_len == 0) {
|
||||
return 0;
|
||||
|
||||
char *kdata = reinterpret_cast<char*>(addr);
|
||||
struct iovec const *iov = i->iov;
|
||||
|
||||
size_t len = bytes;
|
||||
while (len > 0) {
|
||||
if (iov->iov_len) {
|
||||
size_t copy_len = (size_t)len < iov->iov_len ? len : iov->iov_len;
|
||||
Genode::memcpy(kdata, iov->iov_base, copy_len);
|
||||
|
||||
len -= copy_len;
|
||||
kdata += copy_len;
|
||||
i->count -= copy_len; /* XXX the vanilla macro does that */
|
||||
}
|
||||
iov++;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
if (i->nr_segs > 1) {
|
||||
Genode::error(__func__, ": too many segments ", i->nr_segs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* make sure the whole iter fits as there is only 1 iovec */
|
||||
if (i->iov->iov_len < i->count) {
|
||||
Genode::error(__func__, ": "
|
||||
"iov->iov_len: ", i->iov->iov_len, " < "
|
||||
"i->count: ", i->count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct iovec const * const iov = i->iov;
|
||||
size_t const iov_len = iov->iov_len;
|
||||
void * const base = (iov->iov_base + i->iov_offset);
|
||||
|
||||
if (bytes > i->count) { bytes = i->count; }
|
||||
|
||||
size_t const len = (size_t)(bytes < iov_len ? bytes : iov_len);
|
||||
void * const dst = to_iter ? base : addr;
|
||||
void const * const src = to_iter ? addr : base;
|
||||
|
||||
/* actual function body */
|
||||
{
|
||||
Genode::memcpy(dst, src, len);
|
||||
}
|
||||
|
||||
i->iov_offset += len;
|
||||
i->count -= len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
|
||||
{
|
||||
return _copy_iter(addr, bytes, i, false);
|
||||
}
|
||||
|
||||
|
||||
size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i)
|
||||
{
|
||||
if (bytes > i->count)
|
||||
bytes = i->count;
|
||||
|
||||
if (bytes == 0)
|
||||
return 0;
|
||||
|
||||
char *kdata = reinterpret_cast<char*>(addr);
|
||||
struct iovec const *iov = i->iov;
|
||||
|
||||
size_t len = bytes;
|
||||
while (len > 0) {
|
||||
if (iov->iov_len) {
|
||||
size_t copy_len = (size_t)len < iov->iov_len ? len : iov->iov_len;
|
||||
Genode::memcpy(iov->iov_base, kdata, copy_len);
|
||||
|
||||
len -= copy_len;
|
||||
kdata += copy_len;
|
||||
|
||||
i->count -= copy_len; /* XXX the vanilla macro does that */
|
||||
}
|
||||
iov++;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
return _copy_iter(addr, bytes, i, true);
|
||||
}
|
||||
|
||||
|
||||
@ -606,83 +607,69 @@ size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes,
|
||||
}
|
||||
|
||||
|
||||
size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i)
|
||||
static size_t _csum_and_copy_iter(void *addr, size_t bytes, __wsum *csum,
|
||||
struct iov_iter *i, bool to_iter)
|
||||
{
|
||||
if (bytes > i->count)
|
||||
bytes = i->count;
|
||||
if (addr == nullptr) { return 0; }
|
||||
|
||||
if (bytes == 0)
|
||||
if (i->count == 0 ||
|
||||
i->iov == nullptr ||
|
||||
i->iov->iov_len == 0) {
|
||||
return 0;
|
||||
|
||||
char *kdata = reinterpret_cast<char*>(addr);
|
||||
struct iovec const *iov = i->iov;
|
||||
|
||||
__wsum sum = *csum;
|
||||
size_t len = bytes;
|
||||
while (len > 0) {
|
||||
if (iov->iov_len) {
|
||||
size_t copy_len = (size_t)len < iov->iov_len ? len : iov->iov_len;
|
||||
int err = 0;
|
||||
__wsum next = csum_and_copy_from_user(iov->iov_base, kdata, copy_len, 0, &err);
|
||||
|
||||
if (err) {
|
||||
Genode::error(__func__, ": err: ", err, " - sleeping");
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
sum = csum_block_add(sum, next, bytes-len);
|
||||
|
||||
len -= copy_len;
|
||||
kdata += copy_len;
|
||||
|
||||
i->count -= copy_len; /* XXX the vanilla macro does that */
|
||||
}
|
||||
iov++;
|
||||
}
|
||||
|
||||
*csum = sum;
|
||||
if (i->nr_segs > 1) {
|
||||
Genode::error(__func__, ": too many segments ", i->nr_segs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
/* make sure the whole iter fits as there is only 1 iovec */
|
||||
if (i->iov->iov_len < i->count) {
|
||||
Genode::error(__func__, ": "
|
||||
"iov->iov_len: ", i->iov->iov_len, " < "
|
||||
"i->count: ", i->count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct iovec const * const iov = i->iov;
|
||||
size_t const iov_len = iov->iov_len;
|
||||
void * const base = (iov->iov_base + i->iov_offset);
|
||||
|
||||
if (bytes > i->count) { bytes = i->count; }
|
||||
|
||||
size_t const len = (size_t)(bytes < iov_len ? bytes : iov_len);
|
||||
void * const dst = to_iter ? base : addr;
|
||||
void const * const src = to_iter ? addr : base;
|
||||
|
||||
/* actual function body */
|
||||
{
|
||||
int err = 0;
|
||||
__wsum next = csum_and_copy_from_user(src, dst, len, 0, &err);
|
||||
|
||||
if (err) {
|
||||
Genode::error(__func__, ": err: ", err, " - sleeping");
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
*csum = csum_block_add(*csum, next, 0);
|
||||
}
|
||||
|
||||
i->iov_offset += len;
|
||||
i->count -= len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i)
|
||||
{
|
||||
return _csum_and_copy_iter(addr, bytes, csum, i, false);
|
||||
}
|
||||
|
||||
|
||||
size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i)
|
||||
{
|
||||
if (bytes > i->count)
|
||||
bytes = i->count;
|
||||
|
||||
if (bytes == 0)
|
||||
return 0;
|
||||
|
||||
char *kdata = reinterpret_cast<char*>(addr);
|
||||
struct iovec const *iov = i->iov;
|
||||
|
||||
__wsum sum = *csum;
|
||||
size_t len = bytes;
|
||||
while (len > 0) {
|
||||
if (iov->iov_len) {
|
||||
size_t copy_len = (size_t)len < iov->iov_len ? len : iov->iov_len;
|
||||
int err = 0;
|
||||
__wsum next = csum_and_copy_to_user(kdata, iov->iov_base, copy_len, 0, &err);
|
||||
|
||||
if (err) {
|
||||
Genode::error(__func__, ": err: ", err, " - sleeping");
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
sum = csum_block_add(sum, next, bytes-len);
|
||||
|
||||
len -= copy_len;
|
||||
kdata += copy_len;
|
||||
|
||||
i->count -= copy_len; /* XXX the vanilla macro does that */
|
||||
}
|
||||
iov++;
|
||||
}
|
||||
|
||||
*csum = sum;
|
||||
|
||||
return bytes;
|
||||
return _csum_and_copy_iter(addr, bytes, csum, i, true);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user