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>
|
#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 *);
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user