]> Zhao Yanbai Git Server - minix.git/commitdiff
RMIB: add support for vector copy-out 69/3369/1
authorDavid van Moolenbroek <david@minix3.org>
Thu, 20 Oct 2016 11:07:25 +0000 (11:07 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Mon, 24 Oct 2016 12:10:34 +0000 (12:10 +0000)
Change-Id: I9e9b4b8d6eed39fdb511c6bd2a375ddf898064a5

minix/include/minix/rmib.h
minix/lib/libsys/rmib.c
minix/net/inet/rtinfo.c
minix/net/lwip/rtinfo.c

index 0e055a4042e8b222e38f39aced05ae684730fe5d..06b403d8f918c62257ecbfd28a4d6c6cd9da9715 100644 (file)
@@ -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 *);
index d14287efcfb957afecc75c537207c37649da7962..ad96e86447f245cb5e26f7c9fa824beb24510055 100644 (file)
@@ -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.
index 62f3880b0511956e3f912d07f919280f52ae1d98..7235abfa409e9e6913c42453ab00256cb1c03d75 100644 (file)
 
 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
index 878fb3875847b3d3f4781da8a5c829c2d51b3c95..add6609a6f4733fd5f0daa834d62d9c9ab0c8455 100644 (file)
 
 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