RMIB: add support for vector copy-out
Change-Id: I9e9b4b8d6eed39fdb511c6bd2a375ddf898064a5
This commit is contained in:
parent
9f11521a37
commit
f221d2ce48
@ -9,6 +9,12 @@
|
||||
|
||||
#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
|
||||
* 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 *);
|
||||
ssize_t rmib_copyout(struct rmib_oldp *, size_t, const void * __restrict,
|
||||
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);
|
||||
ssize_t rmib_readwrite(struct rmib_call *, struct rmib_node *,
|
||||
struct rmib_oldp *, struct rmib_newp *);
|
||||
|
@ -110,6 +110,60 @@ rmib_copyout(struct rmib_oldp * __restrict oldp, size_t off,
|
||||
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
|
||||
* given by the user. Return OK or an error code.
|
||||
|
@ -26,32 +26,6 @@
|
||||
|
||||
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
|
||||
* interface address record with an associated set of zero or more routing
|
||||
|
@ -23,32 +23,6 @@
|
||||
|
||||
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
|
||||
* interface address record with an associated set of zero or more routing
|
||||
|
Loading…
x
Reference in New Issue
Block a user