Skip to content

Commit

Permalink
lib/ukfile: Add utility inlines for iovec I/O
Browse files Browse the repository at this point in the history
This change adds a utility header providing convenience inlines for
doing I/O on buffers described by struct iovec, namely:
- zero out
- scatter data from buffer to iov
- gather data from iov into buffer

Signed-off-by: Andrei Tatar <andrei@unikraft.io>
  • Loading branch information
andreittr committed May 1, 2024
1 parent 3facdb2 commit 8408167
Showing 1 changed file with 171 additions and 0 deletions.
171 changes: 171 additions & 0 deletions lib/ukfile/include/uk/file/iovutil.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright (c) 2024, Unikraft GmbH and The Unikraft Authors.
* Licensed under the BSD-3-Clause License (the "License").
* You may not use this file except in compliance with the License.
*/

/* Convenience operations for dealing with iovec */

#ifndef __UKFILE_IOVUTIL_H__
#define __UKFILE_IOVUTIL_H__

#include <string.h>
#include <sys/uio.h>

#include <uk/essentials.h>

/**
* Zero out at most `len` bytes in memory regions described by `iov[iovcnt]`,
* starting at `*curp` offset from the buffer at `iov[*iovip]`.
*
* If the total remaining space in `iov` is less than `len`, exit early.
* After the call, `*iovip` and `*curp` are updated with the new positions.
*
* @return Number of bytes zeroed
*/
static inline
size_t uk_iov_zero(const struct iovec *iov, int iovcnt, size_t len,
int *iovip, size_t *curp)
{
size_t ret = 0;
int i = *iovip;
size_t cur = *curp;

UK_ASSERT(i < iovcnt);
UK_ASSERT(cur < iov[i].iov_len);
if (cur) {
const size_t l = MIN(len, iov[i].iov_len - cur);

memset((char *)iov[i].iov_base + cur, 0, l);
ret += l;
len -= l;
cur += l;
if (cur == iov[i].iov_len) {
i++;
cur = 0;
}
}
if (len) {
UK_ASSERT(!cur);
while (i < iovcnt && len) {
const size_t l = MIN(iov[i].iov_len, len);

memset(iov[i].iov_base, 0, l);
ret += l;
len -= l;
if (len)
i++;
else
cur = l;
}
}
*iovip = i;
*curp = cur;
return ret;
}

/**
* Copy at most `len` bytes from `buf` into memory regions described by
* `iov[iovcnt]`, starting at `*curp` offset from the buffer at `iov[*iovip]`.
*
* If the total remaining space in `iov` is less than `len`, exit early.
* After the call, `*iovip` and `*curp` are updated with the new positions.
*
* @return Number of bytes copied
*/
static inline
size_t uk_iov_scatter(const struct iovec *iov, int iovcnt, const char *buf,
size_t len, int *iovip, size_t *curp)
{
size_t ret = 0;
int i = *iovip;
size_t cur = *curp;

UK_ASSERT(i < iovcnt);
UK_ASSERT(cur < iov[i].iov_len);
if (cur) {
const size_t l = MIN(len, iov[i].iov_len - cur);

memcpy((char *)iov[i].iov_base + cur, buf, l);
ret += l;
buf += l;
len -= l;
cur += l;
if (cur == iov[i].iov_len) {
i++;
cur = 0;
}
}
if (len) {
UK_ASSERT(!cur);
while (i < iovcnt && len) {
const size_t l = MIN(iov[i].iov_len, len);

memcpy(iov[i].iov_base, buf, l);
ret += l;
buf += l;
len -= l;
if (len)
i++;
else
cur = l;
}
}
*iovip = i;
*curp = cur;
return ret;
}

/**
* Copy at most `len` bytes from the memory regions described by `iov[iovcnt]`,
* starting at `*curp` offset from the buffer at `iov[*iovip]`, into `buf`.
*
* If the total remaining bytes in `iov` are less than `len`, exit early.
* After the call, `*iovip` and `*curp` are updated with the new positions.
*
* @return Number of bytes copied
*/
static inline
size_t uk_iov_gather(char *buf, const struct iovec *iov, int iovcnt,
size_t len, int *iovip, size_t *curp)
{
size_t ret = 0;
int i = *iovip;
size_t cur = *curp;

UK_ASSERT(i < iovcnt);
UK_ASSERT(cur < iov[i].iov_len);
if (cur) {
const size_t l = MIN(len, iov[i].iov_len - cur);

memcpy(buf, (char *)iov[i].iov_base + cur, l);
ret += l;
buf += l;
len -= l;
cur += l;
if (cur == iov[i].iov_len) {
i++;
cur = 0;
}
}
if (len) {
UK_ASSERT(!cur);
while (i < iovcnt && len) {
const size_t l = MIN(iov[i].iov_len, len);

memcpy(buf, iov[i].iov_base, l);
ret += l;
buf += l;
len -= l;
if (len)
i++;
else
cur = l;
}
}
*iovip = i;
*curp = cur;
return ret;
}

#endif /* __UKFILE_IOVUTIL_H__ */

0 comments on commit 8408167

Please sign in to comment.