[Xenomai-git] Philippe Gerum : cobalt/rtdm: factor out iovec[] copy routines
Module: xenomai-3 Branch: wip/rtnet-fixes Commit: 3a2fbc62b2dce64e959a49db9bcc049e6acc4e21 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=3a2fbc62b2dce64e959a49db9bcc049e6acc4e21 Author: Philippe GerumDate: Tue Dec 5 11:22:59 2017 +0100 cobalt/rtdm: factor out iovec[] copy routines --- include/cobalt/kernel/rtdm/driver.h | 19 + kernel/cobalt/rtdm/drvlib.c | 80 +++ kernel/drivers/ipc/bufp.c | 20 - kernel/drivers/ipc/iddp.c | 20 - kernel/drivers/ipc/internal.h | 19 - kernel/drivers/ipc/rtipc.c | 76 - kernel/drivers/ipc/xddp.c | 20 - 7 files changed, 129 insertions(+), 125 deletions(-) diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h index 0c7b62e..63beb48 100644 --- a/include/cobalt/kernel/rtdm/driver.h +++ b/include/cobalt/kernel/rtdm/driver.h @@ -1339,6 +1339,25 @@ static inline int rtdm_in_rt_context(void) return (ipipe_current_domain != ipipe_root_domain); } +#define RTDM_IOV_FASTMAX 16 + +int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iov, + const struct user_msghdr *msg, + struct iovec *iov_fast); + +int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov, + const struct user_msghdr *msg, + struct iovec *iov_fast); + +static inline +void rtdm_drop_iovec(struct iovec *iov, struct iovec *iov_fast) +{ + if (iov != iov_fast) + xnfree(iov); +} + +ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen); + #endif /* !DOXYGEN_CPP */ #endif /* _COBALT_RTDM_DRIVER_H */ diff --git a/kernel/cobalt/rtdm/drvlib.c b/kernel/cobalt/rtdm/drvlib.c index fb7bd7e..847e18f 100644 --- a/kernel/cobalt/rtdm/drvlib.c +++ b/kernel/cobalt/rtdm/drvlib.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "internal.h" #include @@ -2151,6 +2152,85 @@ int rtdm_ratelimit(struct rtdm_ratelimit_state *rs, const char *func) } EXPORT_SYMBOL_GPL(rtdm_ratelimit); +int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iovp, + const struct user_msghdr *msg, + struct iovec *iov_fast) +{ + size_t len = sizeof(struct iovec) * msg->msg_iovlen; + struct iovec *iov = iov_fast; + + /* +* If the I/O vector doesn't fit in the fast memory, allocate +* a chunk from the system heap which is large enough to hold +* it. +*/ + if (msg->msg_iovlen > RTDM_IOV_FASTMAX) { + iov = xnmalloc(len); + if (iov == NULL) + return -ENOMEM; + } + + *iovp = iov; + + if (!rtdm_fd_is_user(fd)) { + memcpy(iov, msg->msg_iov, len); + return 0; + } + +#ifdef CONFIG_XENO_ARCH_SYS3264 + if (rtdm_fd_is_compat(fd)) + return sys32_get_iovec(iov, + (struct compat_iovec __user *)msg->msg_iov, + msg->msg_iovlen); +#endif + + return rtdm_copy_from_user(fd, iov, msg->msg_iov, len); +} +EXPORT_SYMBOL_GPL(rtdm_get_iovec); + +int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov, + const struct user_msghdr *msg, + struct iovec *iov_fast) +{ + size_t len = sizeof(iov[0]) * msg->msg_iovlen; + int ret; + + if (!rtdm_fd_is_user(fd)) { + memcpy(msg->msg_iov, iov, len); + ret = 0; + } else +#ifdef CONFIG_XENO_ARCH_SYS3264 + if (rtdm_fd_is_compat(fd)) + ret = sys32_put_iovec((struct compat_iovec __user *)msg->msg_iov, + iov, msg->msg_iovlen); + else +#endif + ret = rtdm_copy_to_user(fd, msg->msg_iov, iov, len); + + if (iov != iov_fast) + xnfree(iov); + + return ret; +} +EXPORT_SYMBOL_GPL(rtdm_put_iovec); + +ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen) +{ + ssize_t len; + int nvec; + + /* Return the flattened vector length. */ + for (len = 0, nvec = 0; nvec < iovlen; nvec++) { + ssize_t l = iov[nvec].iov_len; + if (l < 0 || len + l < len) /* SuS wants this. */ + return -EINVAL; + len += l; + } + + return len; +} +EXPORT_SYMBOL_GPL(rtdm_get_iov_flatlen); + #ifdef DOXYGEN_CPP /* Only used for doxygen doc generation */ /** diff --git a/kernel/drivers/ipc/bufp.c b/kernel/drivers/ipc/bufp.c index 3b565bd..e1c8672 100644 --- a/kernel/drivers/ipc/bufp.c +++ b/kernel/drivers/ipc/bufp.c @@ -307,7 +307,7 @@ static ssize_t __bufp_recvmsg(struct rtdm_fd *fd, if (!test_bit(_BUFP_BOUND, >status)) return -EAGAIN; - len = rtipc_get_iov_flatlen(iov, iovlen); + len =
[Xenomai-git] Philippe Gerum : cobalt/rtdm: factor out iovec[] copy routines
Module: xenomai-3 Branch: stable-3.0.x Commit: 3a2fbc62b2dce64e959a49db9bcc049e6acc4e21 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=3a2fbc62b2dce64e959a49db9bcc049e6acc4e21 Author: Philippe GerumDate: Tue Dec 5 11:22:59 2017 +0100 cobalt/rtdm: factor out iovec[] copy routines --- include/cobalt/kernel/rtdm/driver.h | 19 + kernel/cobalt/rtdm/drvlib.c | 80 +++ kernel/drivers/ipc/bufp.c | 20 - kernel/drivers/ipc/iddp.c | 20 - kernel/drivers/ipc/internal.h | 19 - kernel/drivers/ipc/rtipc.c | 76 - kernel/drivers/ipc/xddp.c | 20 - 7 files changed, 129 insertions(+), 125 deletions(-) diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h index 0c7b62e..63beb48 100644 --- a/include/cobalt/kernel/rtdm/driver.h +++ b/include/cobalt/kernel/rtdm/driver.h @@ -1339,6 +1339,25 @@ static inline int rtdm_in_rt_context(void) return (ipipe_current_domain != ipipe_root_domain); } +#define RTDM_IOV_FASTMAX 16 + +int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iov, + const struct user_msghdr *msg, + struct iovec *iov_fast); + +int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov, + const struct user_msghdr *msg, + struct iovec *iov_fast); + +static inline +void rtdm_drop_iovec(struct iovec *iov, struct iovec *iov_fast) +{ + if (iov != iov_fast) + xnfree(iov); +} + +ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen); + #endif /* !DOXYGEN_CPP */ #endif /* _COBALT_RTDM_DRIVER_H */ diff --git a/kernel/cobalt/rtdm/drvlib.c b/kernel/cobalt/rtdm/drvlib.c index fb7bd7e..847e18f 100644 --- a/kernel/cobalt/rtdm/drvlib.c +++ b/kernel/cobalt/rtdm/drvlib.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "internal.h" #include @@ -2151,6 +2152,85 @@ int rtdm_ratelimit(struct rtdm_ratelimit_state *rs, const char *func) } EXPORT_SYMBOL_GPL(rtdm_ratelimit); +int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iovp, + const struct user_msghdr *msg, + struct iovec *iov_fast) +{ + size_t len = sizeof(struct iovec) * msg->msg_iovlen; + struct iovec *iov = iov_fast; + + /* +* If the I/O vector doesn't fit in the fast memory, allocate +* a chunk from the system heap which is large enough to hold +* it. +*/ + if (msg->msg_iovlen > RTDM_IOV_FASTMAX) { + iov = xnmalloc(len); + if (iov == NULL) + return -ENOMEM; + } + + *iovp = iov; + + if (!rtdm_fd_is_user(fd)) { + memcpy(iov, msg->msg_iov, len); + return 0; + } + +#ifdef CONFIG_XENO_ARCH_SYS3264 + if (rtdm_fd_is_compat(fd)) + return sys32_get_iovec(iov, + (struct compat_iovec __user *)msg->msg_iov, + msg->msg_iovlen); +#endif + + return rtdm_copy_from_user(fd, iov, msg->msg_iov, len); +} +EXPORT_SYMBOL_GPL(rtdm_get_iovec); + +int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov, + const struct user_msghdr *msg, + struct iovec *iov_fast) +{ + size_t len = sizeof(iov[0]) * msg->msg_iovlen; + int ret; + + if (!rtdm_fd_is_user(fd)) { + memcpy(msg->msg_iov, iov, len); + ret = 0; + } else +#ifdef CONFIG_XENO_ARCH_SYS3264 + if (rtdm_fd_is_compat(fd)) + ret = sys32_put_iovec((struct compat_iovec __user *)msg->msg_iov, + iov, msg->msg_iovlen); + else +#endif + ret = rtdm_copy_to_user(fd, msg->msg_iov, iov, len); + + if (iov != iov_fast) + xnfree(iov); + + return ret; +} +EXPORT_SYMBOL_GPL(rtdm_put_iovec); + +ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen) +{ + ssize_t len; + int nvec; + + /* Return the flattened vector length. */ + for (len = 0, nvec = 0; nvec < iovlen; nvec++) { + ssize_t l = iov[nvec].iov_len; + if (l < 0 || len + l < len) /* SuS wants this. */ + return -EINVAL; + len += l; + } + + return len; +} +EXPORT_SYMBOL_GPL(rtdm_get_iov_flatlen); + #ifdef DOXYGEN_CPP /* Only used for doxygen doc generation */ /** diff --git a/kernel/drivers/ipc/bufp.c b/kernel/drivers/ipc/bufp.c index 3b565bd..e1c8672 100644 --- a/kernel/drivers/ipc/bufp.c +++ b/kernel/drivers/ipc/bufp.c @@ -307,7 +307,7 @@ static ssize_t __bufp_recvmsg(struct rtdm_fd *fd, if (!test_bit(_BUFP_BOUND, >status)) return -EAGAIN; - len = rtipc_get_iov_flatlen(iov, iovlen); + len =
[Xenomai-git] Philippe Gerum : cobalt/rtdm: factor out iovec[] copy routines
Module: xenomai-3 Branch: wip/rtnet-fixes Commit: 103a67cac3c7560e8b5e0b9551401968b79ae1e4 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=103a67cac3c7560e8b5e0b9551401968b79ae1e4 Author: Philippe GerumDate: Tue Dec 5 11:22:59 2017 +0100 cobalt/rtdm: factor out iovec[] copy routines --- include/cobalt/kernel/rtdm/driver.h | 19 + kernel/cobalt/rtdm/drvlib.c | 80 +++ kernel/drivers/ipc/bufp.c | 20 - kernel/drivers/ipc/iddp.c | 20 - kernel/drivers/ipc/internal.h | 19 - kernel/drivers/ipc/rtipc.c | 76 - kernel/drivers/ipc/xddp.c | 20 - 7 files changed, 129 insertions(+), 125 deletions(-) diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h index 0c7b62e..63beb48 100644 --- a/include/cobalt/kernel/rtdm/driver.h +++ b/include/cobalt/kernel/rtdm/driver.h @@ -1339,6 +1339,25 @@ static inline int rtdm_in_rt_context(void) return (ipipe_current_domain != ipipe_root_domain); } +#define RTDM_IOV_FASTMAX 16 + +int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iov, + const struct user_msghdr *msg, + struct iovec *iov_fast); + +int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov, + const struct user_msghdr *msg, + struct iovec *iov_fast); + +static inline +void rtdm_drop_iovec(struct iovec *iov, struct iovec *iov_fast) +{ + if (iov != iov_fast) + xnfree(iov); +} + +ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen); + #endif /* !DOXYGEN_CPP */ #endif /* _COBALT_RTDM_DRIVER_H */ diff --git a/kernel/cobalt/rtdm/drvlib.c b/kernel/cobalt/rtdm/drvlib.c index fb7bd7e..847e18f 100644 --- a/kernel/cobalt/rtdm/drvlib.c +++ b/kernel/cobalt/rtdm/drvlib.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "internal.h" #include @@ -2151,6 +2152,85 @@ int rtdm_ratelimit(struct rtdm_ratelimit_state *rs, const char *func) } EXPORT_SYMBOL_GPL(rtdm_ratelimit); +int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iovp, + const struct user_msghdr *msg, + struct iovec *iov_fast) +{ + size_t len = sizeof(struct iovec) * msg->msg_iovlen; + struct iovec *iov = iov_fast; + + /* +* If the I/O vector doesn't fit in the fast memory, allocate +* a chunk from the system heap which is large enough to hold +* it. +*/ + if (msg->msg_iovlen > RTDM_IOV_FASTMAX) { + iov = xnmalloc(len); + if (iov == NULL) + return -ENOMEM; + } + + *iovp = iov; + + if (!rtdm_fd_is_user(fd)) { + memcpy(iov, msg->msg_iov, len); + return 0; + } + +#ifdef CONFIG_XENO_ARCH_SYS3264 + if (rtdm_fd_is_compat(fd)) + return sys32_get_iovec(iov, + (struct compat_iovec __user *)msg->msg_iov, + msg->msg_iovlen); +#endif + + return rtdm_copy_from_user(fd, iov, msg->msg_iov, len); +} +EXPORT_SYMBOL_GPL(rtdm_get_iovec); + +int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov, + const struct user_msghdr *msg, + struct iovec *iov_fast) +{ + size_t len = sizeof(iov[0]) * msg->msg_iovlen; + int ret; + + if (!rtdm_fd_is_user(fd)) { + memcpy(msg->msg_iov, iov, len); + ret = 0; + } else +#ifdef CONFIG_XENO_ARCH_SYS3264 + if (rtdm_fd_is_compat(fd)) + ret = sys32_put_iovec((struct compat_iovec __user *)msg->msg_iov, + iov, msg->msg_iovlen); + else +#endif + ret = rtdm_copy_to_user(fd, msg->msg_iov, iov, len); + + if (iov != iov_fast) + xnfree(iov); + + return ret; +} +EXPORT_SYMBOL_GPL(rtdm_put_iovec); + +ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen) +{ + ssize_t len; + int nvec; + + /* Return the flattened vector length. */ + for (len = 0, nvec = 0; nvec < iovlen; nvec++) { + ssize_t l = iov[nvec].iov_len; + if (l < 0 || len + l < len) /* SuS wants this. */ + return -EINVAL; + len += l; + } + + return len; +} +EXPORT_SYMBOL_GPL(rtdm_get_iov_flatlen); + #ifdef DOXYGEN_CPP /* Only used for doxygen doc generation */ /** diff --git a/kernel/drivers/ipc/bufp.c b/kernel/drivers/ipc/bufp.c index 3b565bd..e1c8672 100644 --- a/kernel/drivers/ipc/bufp.c +++ b/kernel/drivers/ipc/bufp.c @@ -307,7 +307,7 @@ static ssize_t __bufp_recvmsg(struct rtdm_fd *fd, if (!test_bit(_BUFP_BOUND, >status)) return -EAGAIN; - len = rtipc_get_iov_flatlen(iov, iovlen); + len =
[Xenomai-git] Philippe Gerum : cobalt/rtdm: factor out iovec[] copy routines
Module: xenomai-3 Branch: wip/rtnet-fixes Commit: 33c43f43cf6d8851e08424e0ad15a42c5d88c2bf URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=33c43f43cf6d8851e08424e0ad15a42c5d88c2bf Author: Philippe GerumDate: Tue Dec 5 11:22:59 2017 +0100 cobalt/rtdm: factor out iovec[] copy routines --- include/cobalt/kernel/rtdm/driver.h | 19 + kernel/cobalt/rtdm/drvlib.c | 80 +++ kernel/drivers/ipc/bufp.c | 20 - kernel/drivers/ipc/iddp.c | 20 - kernel/drivers/ipc/internal.h | 19 - kernel/drivers/ipc/rtipc.c | 76 - kernel/drivers/ipc/xddp.c | 20 - 7 files changed, 129 insertions(+), 125 deletions(-) diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h index 0c7b62e..63beb48 100644 --- a/include/cobalt/kernel/rtdm/driver.h +++ b/include/cobalt/kernel/rtdm/driver.h @@ -1339,6 +1339,25 @@ static inline int rtdm_in_rt_context(void) return (ipipe_current_domain != ipipe_root_domain); } +#define RTDM_IOV_FASTMAX 16 + +int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iov, + const struct user_msghdr *msg, + struct iovec *iov_fast); + +int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov, + const struct user_msghdr *msg, + struct iovec *iov_fast); + +static inline +void rtdm_drop_iovec(struct iovec *iov, struct iovec *iov_fast) +{ + if (iov != iov_fast) + xnfree(iov); +} + +ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen); + #endif /* !DOXYGEN_CPP */ #endif /* _COBALT_RTDM_DRIVER_H */ diff --git a/kernel/cobalt/rtdm/drvlib.c b/kernel/cobalt/rtdm/drvlib.c index fb7bd7e..847e18f 100644 --- a/kernel/cobalt/rtdm/drvlib.c +++ b/kernel/cobalt/rtdm/drvlib.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "internal.h" #include @@ -2151,6 +2152,85 @@ int rtdm_ratelimit(struct rtdm_ratelimit_state *rs, const char *func) } EXPORT_SYMBOL_GPL(rtdm_ratelimit); +int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iovp, + const struct user_msghdr *msg, + struct iovec *iov_fast) +{ + size_t len = sizeof(struct iovec) * msg->msg_iovlen; + struct iovec *iov = iov_fast; + + /* +* If the I/O vector doesn't fit in the fast memory, allocate +* a chunk from the system heap which is large enough to hold +* it. +*/ + if (msg->msg_iovlen > RTDM_IOV_FASTMAX) { + iov = xnmalloc(len); + if (iov == NULL) + return -ENOMEM; + } + + *iovp = iov; + + if (!rtdm_fd_is_user(fd)) { + memcpy(iov, msg->msg_iov, len); + return 0; + } + +#ifdef CONFIG_XENO_ARCH_SYS3264 + if (rtdm_fd_is_compat(fd)) + return sys32_get_iovec(iov, + (struct compat_iovec __user *)msg->msg_iov, + msg->msg_iovlen); +#endif + + return rtdm_copy_from_user(fd, iov, msg->msg_iov, len); +} +EXPORT_SYMBOL_GPL(rtdm_get_iovec); + +int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov, + const struct user_msghdr *msg, + struct iovec *iov_fast) +{ + size_t len = sizeof(iov[0]) * msg->msg_iovlen; + int ret; + + if (!rtdm_fd_is_user(fd)) { + memcpy(msg->msg_iov, iov, len); + ret = 0; + } else +#ifdef CONFIG_XENO_ARCH_SYS3264 + if (rtdm_fd_is_compat(fd)) + ret = sys32_put_iovec((struct compat_iovec __user *)msg->msg_iov, + iov, msg->msg_iovlen); + else +#endif + ret = rtdm_copy_to_user(fd, msg->msg_iov, iov, len); + + if (iov != iov_fast) + xnfree(iov); + + return ret; +} +EXPORT_SYMBOL_GPL(rtdm_put_iovec); + +ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen) +{ + ssize_t len; + int nvec; + + /* Return the flattened vector length. */ + for (len = 0, nvec = 0; nvec < iovlen; nvec++) { + ssize_t l = iov[nvec].iov_len; + if (l < 0 || len + l < len) /* SuS wants this. */ + return -EINVAL; + len += l; + } + + return len; +} +EXPORT_SYMBOL_GPL(rtdm_get_iov_flatlen); + #ifdef DOXYGEN_CPP /* Only used for doxygen doc generation */ /** diff --git a/kernel/drivers/ipc/bufp.c b/kernel/drivers/ipc/bufp.c index 3b565bd..e1c8672 100644 --- a/kernel/drivers/ipc/bufp.c +++ b/kernel/drivers/ipc/bufp.c @@ -307,7 +307,7 @@ static ssize_t __bufp_recvmsg(struct rtdm_fd *fd, if (!test_bit(_BUFP_BOUND, >status)) return -EAGAIN; - len = rtipc_get_iov_flatlen(iov, iovlen); + len =
[Xenomai-git] Philippe Gerum : cobalt/rtdm: factor out iovec[] copy routines
Module: xenomai-3 Branch: wip/rtnet-fixes Commit: 9a5a058a6fde92f7286928907a83cb47ae144a95 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=9a5a058a6fde92f7286928907a83cb47ae144a95 Author: Philippe GerumDate: Tue Dec 5 11:22:59 2017 +0100 cobalt/rtdm: factor out iovec[] copy routines --- include/cobalt/kernel/rtdm/driver.h | 19 + kernel/cobalt/rtdm/drvlib.c | 80 +++ kernel/drivers/ipc/bufp.c | 20 - kernel/drivers/ipc/iddp.c | 20 - kernel/drivers/ipc/internal.h | 19 - kernel/drivers/ipc/rtipc.c | 76 - kernel/drivers/ipc/xddp.c | 20 - 7 files changed, 129 insertions(+), 125 deletions(-) diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h index 0c7b62e..63beb48 100644 --- a/include/cobalt/kernel/rtdm/driver.h +++ b/include/cobalt/kernel/rtdm/driver.h @@ -1339,6 +1339,25 @@ static inline int rtdm_in_rt_context(void) return (ipipe_current_domain != ipipe_root_domain); } +#define RTDM_IOV_FASTMAX 16 + +int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iov, + const struct user_msghdr *msg, + struct iovec *iov_fast); + +int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov, + const struct user_msghdr *msg, + struct iovec *iov_fast); + +static inline +void rtdm_drop_iovec(struct iovec *iov, struct iovec *iov_fast) +{ + if (iov != iov_fast) + xnfree(iov); +} + +ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen); + #endif /* !DOXYGEN_CPP */ #endif /* _COBALT_RTDM_DRIVER_H */ diff --git a/kernel/cobalt/rtdm/drvlib.c b/kernel/cobalt/rtdm/drvlib.c index fb7bd7e..847e18f 100644 --- a/kernel/cobalt/rtdm/drvlib.c +++ b/kernel/cobalt/rtdm/drvlib.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "internal.h" #include @@ -2151,6 +2152,85 @@ int rtdm_ratelimit(struct rtdm_ratelimit_state *rs, const char *func) } EXPORT_SYMBOL_GPL(rtdm_ratelimit); +int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iovp, + const struct user_msghdr *msg, + struct iovec *iov_fast) +{ + size_t len = sizeof(struct iovec) * msg->msg_iovlen; + struct iovec *iov = iov_fast; + + /* +* If the I/O vector doesn't fit in the fast memory, allocate +* a chunk from the system heap which is large enough to hold +* it. +*/ + if (msg->msg_iovlen > RTDM_IOV_FASTMAX) { + iov = xnmalloc(len); + if (iov == NULL) + return -ENOMEM; + } + + *iovp = iov; + + if (!rtdm_fd_is_user(fd)) { + memcpy(iov, msg->msg_iov, len); + return 0; + } + +#ifdef CONFIG_XENO_ARCH_SYS3264 + if (rtdm_fd_is_compat(fd)) + return sys32_get_iovec(iov, + (struct compat_iovec __user *)msg->msg_iov, + msg->msg_iovlen); +#endif + + return rtdm_copy_from_user(fd, iov, msg->msg_iov, len); +} +EXPORT_SYMBOL_GPL(rtdm_get_iovec); + +int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov, + const struct user_msghdr *msg, + struct iovec *iov_fast) +{ + size_t len = sizeof(iov[0]) * msg->msg_iovlen; + int ret; + + if (!rtdm_fd_is_user(fd)) { + memcpy(msg->msg_iov, iov, len); + ret = 0; + } else +#ifdef CONFIG_XENO_ARCH_SYS3264 + if (rtdm_fd_is_compat(fd)) + ret = sys32_put_iovec((struct compat_iovec __user *)msg->msg_iov, + iov, msg->msg_iovlen); + else +#endif + ret = rtdm_copy_to_user(fd, msg->msg_iov, iov, len); + + if (iov != iov_fast) + xnfree(iov); + + return ret; +} +EXPORT_SYMBOL_GPL(rtdm_put_iovec); + +ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen) +{ + ssize_t len; + int nvec; + + /* Return the flattened vector length. */ + for (len = 0, nvec = 0; nvec < iovlen; nvec++) { + ssize_t l = iov[nvec].iov_len; + if (l < 0 || len + l < len) /* SuS wants this. */ + return -EINVAL; + len += l; + } + + return len; +} +EXPORT_SYMBOL_GPL(rtdm_get_iov_flatlen); + #ifdef DOXYGEN_CPP /* Only used for doxygen doc generation */ /** diff --git a/kernel/drivers/ipc/bufp.c b/kernel/drivers/ipc/bufp.c index 3b565bd..e1c8672 100644 --- a/kernel/drivers/ipc/bufp.c +++ b/kernel/drivers/ipc/bufp.c @@ -307,7 +307,7 @@ static ssize_t __bufp_recvmsg(struct rtdm_fd *fd, if (!test_bit(_BUFP_BOUND, >status)) return -EAGAIN; - len = rtipc_get_iov_flatlen(iov, iovlen); + len =
[Xenomai-git] Philippe Gerum : cobalt/rtdm: factor out iovec[] copy routines
Module: xenomai-3 Branch: wip/rtnet-fixes Commit: 439ee1bc1e8bfcc29a51c5d15d434b6373a4f79f URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=439ee1bc1e8bfcc29a51c5d15d434b6373a4f79f Author: Philippe GerumDate: Tue Dec 5 11:22:59 2017 +0100 cobalt/rtdm: factor out iovec[] copy routines --- include/cobalt/kernel/rtdm/driver.h | 19 + kernel/cobalt/rtdm/drvlib.c | 80 +++ kernel/drivers/ipc/bufp.c | 20 - kernel/drivers/ipc/iddp.c | 20 - kernel/drivers/ipc/internal.h | 19 - kernel/drivers/ipc/rtipc.c | 76 - kernel/drivers/ipc/xddp.c | 20 - 7 files changed, 129 insertions(+), 125 deletions(-) diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h index 0c7b62e..63beb48 100644 --- a/include/cobalt/kernel/rtdm/driver.h +++ b/include/cobalt/kernel/rtdm/driver.h @@ -1339,6 +1339,25 @@ static inline int rtdm_in_rt_context(void) return (ipipe_current_domain != ipipe_root_domain); } +#define RTDM_IOV_FASTMAX 16 + +int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iov, + const struct user_msghdr *msg, + struct iovec *iov_fast); + +int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov, + const struct user_msghdr *msg, + struct iovec *iov_fast); + +static inline +void rtdm_drop_iovec(struct iovec *iov, struct iovec *iov_fast) +{ + if (iov != iov_fast) + xnfree(iov); +} + +ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen); + #endif /* !DOXYGEN_CPP */ #endif /* _COBALT_RTDM_DRIVER_H */ diff --git a/kernel/cobalt/rtdm/drvlib.c b/kernel/cobalt/rtdm/drvlib.c index fb7bd7e..847e18f 100644 --- a/kernel/cobalt/rtdm/drvlib.c +++ b/kernel/cobalt/rtdm/drvlib.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "internal.h" #include @@ -2151,6 +2152,85 @@ int rtdm_ratelimit(struct rtdm_ratelimit_state *rs, const char *func) } EXPORT_SYMBOL_GPL(rtdm_ratelimit); +int rtdm_get_iovec(struct rtdm_fd *fd, struct iovec **iovp, + const struct user_msghdr *msg, + struct iovec *iov_fast) +{ + size_t len = sizeof(struct iovec) * msg->msg_iovlen; + struct iovec *iov = iov_fast; + + /* +* If the I/O vector doesn't fit in the fast memory, allocate +* a chunk from the system heap which is large enough to hold +* it. +*/ + if (msg->msg_iovlen > RTDM_IOV_FASTMAX) { + iov = xnmalloc(len); + if (iov == NULL) + return -ENOMEM; + } + + *iovp = iov; + + if (!rtdm_fd_is_user(fd)) { + memcpy(iov, msg->msg_iov, len); + return 0; + } + +#ifdef CONFIG_XENO_ARCH_SYS3264 + if (rtdm_fd_is_compat(fd)) + return sys32_get_iovec(iov, + (struct compat_iovec __user *)msg->msg_iov, + msg->msg_iovlen); +#endif + + return rtdm_copy_from_user(fd, iov, msg->msg_iov, len); +} +EXPORT_SYMBOL_GPL(rtdm_get_iovec); + +int rtdm_put_iovec(struct rtdm_fd *fd, struct iovec *iov, + const struct user_msghdr *msg, + struct iovec *iov_fast) +{ + size_t len = sizeof(iov[0]) * msg->msg_iovlen; + int ret; + + if (!rtdm_fd_is_user(fd)) { + memcpy(msg->msg_iov, iov, len); + ret = 0; + } else +#ifdef CONFIG_XENO_ARCH_SYS3264 + if (rtdm_fd_is_compat(fd)) + ret = sys32_put_iovec((struct compat_iovec __user *)msg->msg_iov, + iov, msg->msg_iovlen); + else +#endif + ret = rtdm_copy_to_user(fd, msg->msg_iov, iov, len); + + if (iov != iov_fast) + xnfree(iov); + + return ret; +} +EXPORT_SYMBOL_GPL(rtdm_put_iovec); + +ssize_t rtdm_get_iov_flatlen(struct iovec *iov, int iovlen) +{ + ssize_t len; + int nvec; + + /* Return the flattened vector length. */ + for (len = 0, nvec = 0; nvec < iovlen; nvec++) { + ssize_t l = iov[nvec].iov_len; + if (l < 0 || len + l < len) /* SuS wants this. */ + return -EINVAL; + len += l; + } + + return len; +} +EXPORT_SYMBOL_GPL(rtdm_get_iov_flatlen); + #ifdef DOXYGEN_CPP /* Only used for doxygen doc generation */ /** diff --git a/kernel/drivers/ipc/bufp.c b/kernel/drivers/ipc/bufp.c index 3b565bd..e1c8672 100644 --- a/kernel/drivers/ipc/bufp.c +++ b/kernel/drivers/ipc/bufp.c @@ -307,7 +307,7 @@ static ssize_t __bufp_recvmsg(struct rtdm_fd *fd, if (!test_bit(_BUFP_BOUND, >status)) return -EAGAIN; - len = rtipc_get_iov_flatlen(iov, iovlen); + len =