RMIB: add support for vector copy-out

Change-Id: I9e9b4b8d6eed39fdb511c6bd2a375ddf898064a5
This commit is contained in:
David van Moolenbroek 2016-10-20 11:07:25 +00:00
parent 9f11521a37
commit f221d2ce48
4 changed files with 62 additions and 52 deletions

View File

@ -9,6 +9,12 @@
#include <sys/sysctl.h> #include <sys/sysctl.h>
/*
* The maximum number of I/O vector elements that can be passed to the
* rmib_vcopyout function.
*/
#define RMIB_IOV_MAX SCPVEC_NR
/* /*
* This structure contains a number of less heavily used parameters for handler * This structure contains a number of less heavily used parameters for handler
* functions, mainly to provide extensibility while limiting argument clutter. * functions, mainly to provide extensibility while limiting argument clutter.
@ -145,6 +151,8 @@ int rmib_inrange(struct rmib_oldp *, size_t);
size_t rmib_getoldlen(struct rmib_oldp *); size_t rmib_getoldlen(struct rmib_oldp *);
ssize_t rmib_copyout(struct rmib_oldp *, size_t, const void * __restrict, ssize_t rmib_copyout(struct rmib_oldp *, size_t, const void * __restrict,
size_t); size_t);
ssize_t rmib_vcopyout(struct rmib_oldp *, size_t, const iovec_t *,
unsigned int);
int rmib_copyin(struct rmib_newp * __restrict, void * __restrict, size_t); int rmib_copyin(struct rmib_newp * __restrict, void * __restrict, size_t);
ssize_t rmib_readwrite(struct rmib_call *, struct rmib_node *, ssize_t rmib_readwrite(struct rmib_call *, struct rmib_node *,
struct rmib_oldp *, struct rmib_newp *); struct rmib_oldp *, struct rmib_newp *);

View File

@ -110,6 +110,60 @@ rmib_copyout(struct rmib_oldp * __restrict oldp, size_t off,
return size; return size;
} }
/*
* Copy out (partial) data to the user, from a vector of up to RMIB_IOV_MAX
* local buffers. The copy is automatically limited to the range of data
* requested by the user. Return the total requested length on success or an
* error code on failure.
*/
ssize_t
rmib_vcopyout(struct rmib_oldp * oldp, size_t off, const iovec_t * iov,
unsigned int iovcnt)
{
static struct vscp_vec vec[RMIB_IOV_MAX];
size_t size, chunk;
unsigned int i;
ssize_t r;
assert(iov != NULL);
assert(iovcnt <= __arraycount(vec));
/* Take a shortcut for single-vector elements, saving a kernel copy. */
if (iovcnt == 1)
return rmib_copyout(oldp, off, (const void *)iov->iov_addr,
iov->iov_size);
/*
* Iterate through the full vector even if we cannot copy out all of
* it, because we need to compute the total length.
*/
for (size = i = 0; iovcnt > 0; iov++, iovcnt--) {
if (oldp != NULL && off < oldp->oldp_len) {
chunk = oldp->oldp_len - off;
if (chunk > iov->iov_size)
chunk = iov->iov_size;
vec[i].v_from = SELF;
vec[i].v_to = MIB_PROC_NR;
vec[i].v_gid = oldp->oldp_grant;
vec[i].v_offset = off;
vec[i].v_addr = iov->iov_addr;
vec[i].v_bytes = chunk;
off += chunk;
i++;
}
size += iov->iov_size;
}
/* Perform the copy, if there is anything to copy, that is. */
if (i > 0 && (r = sys_vsafecopy(vec, i)) != OK)
return r;
return size;
}
/* /*
* Copy in data from the user. The given length must match exactly the length * Copy in data from the user. The given length must match exactly the length
* given by the user. Return OK or an error code. * given by the user. Return OK or an error code.

View File

@ -26,32 +26,6 @@
static const char padbuf[RT_ROUNDUP(0)] = { 0 }; static const char padbuf[RT_ROUNDUP(0)] = { 0 };
/*
* Copy out a vector of data to the sysctl(2) caller. TODO: decide what to do
* with this. We could implement this as a vectored-safecopy operation in
* RMIB. We could also copy everything into a single buffer first. The
* current implementation is probably the worst among the possibilities.
*/
static ssize_t
rmib_vcopyout(struct rmib_oldp * oldp, size_t off, const iovec_t * iov,
unsigned int iovcnt)
{
unsigned int i;
ssize_t r, len;
len = 0;
for (i = 0; i < iovcnt; i++) {
if ((r = rmib_copyout(oldp, off + len,
(const void *)iov[i].iov_addr, iov[i].iov_size)) < 0)
return r;
len += r;
}
return len;
}
/* /*
* Compute the length for, and possibly copy out, an interface information or * Compute the length for, and possibly copy out, an interface information or
* interface address record with an associated set of zero or more routing * interface address record with an associated set of zero or more routing

View File

@ -23,32 +23,6 @@
static const char padbuf[RT_ROUNDUP(0)] = { 0 }; static const char padbuf[RT_ROUNDUP(0)] = { 0 };
/*
* Copy out a vector of data to the sysctl(2) caller. TODO: decide what to do
* with this. We could implement this as a vectored-safecopy operation in
* RMIB. We could also copy everything into a single buffer first. The
* current implementation is probably the worst among the possibilities.
*/
static ssize_t
rmib_vcopyout(struct rmib_oldp * oldp, size_t off, const iovec_t * iov,
unsigned int iovcnt)
{
unsigned int i;
ssize_t r, len;
len = 0;
for (i = 0; i < iovcnt; i++) {
if ((r = rmib_copyout(oldp, off + len,
(const void *)iov[i].iov_addr, iov[i].iov_size)) < 0)
return r;
len += r;
}
return len;
}
/* /*
* Compute the length for, and possibly copy out, an interface information or * Compute the length for, and possibly copy out, an interface information or
* interface address record with an associated set of zero or more routing * interface address record with an associated set of zero or more routing