Module: xenomai-forge Branch: next Commit: 19e2031e5f488e98807fb0092abf8072dfe45892 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=19e2031e5f488e98807fb0092abf8072dfe45892
Author: Philippe Gerum <r...@xenomai.org> Date: Fri Sep 19 17:10:45 2014 +0200 cobalt/rtdm: split user/kernel paths to opening device This is preparation work before we may get rid of our private fd allocation system for in-kernel callers. --- include/cobalt/kernel/rtdm/rtdm.h | 10 +- kernel/cobalt/posix/io.c | 61 +---------- kernel/cobalt/rtdm/core.c | 215 ++++++++++++++++++++++++++++++------- kernel/cobalt/rtdm/internal.h | 14 ++- 4 files changed, 194 insertions(+), 106 deletions(-) diff --git a/include/cobalt/kernel/rtdm/rtdm.h b/include/cobalt/kernel/rtdm/rtdm.h index 645cb9a..98f0d3a 100644 --- a/include/cobalt/kernel/rtdm/rtdm.h +++ b/include/cobalt/kernel/rtdm/rtdm.h @@ -32,10 +32,10 @@ typedef u32 socklen_t; -int __rt_dev_open(struct xnsys_ppd *p, int ufd, const char *path, int oflag); +int __rtdm_dev_kopen(const char *path, int oflag); -int __rt_dev_socket(struct xnsys_ppd *p, int ufd, - int protocol_family, int socket_type, int protocol); +int __rtdm_dev_ksocket(int protocol_family, int socket_type, + int protocol); int __rt_dev_ioctl_fallback(struct rtdm_fd *fd, unsigned request, void __user *arg); @@ -47,10 +47,10 @@ __rt_dev_ioctl_fallback(struct rtdm_fd *fd, unsigned request, void __user *arg); #ifndef RTDM_NO_DEFAULT_USER_API #define rt_dev_open(path, oflag, ...) \ - __rt_dev_open(&__xnsys_global_ppd, -1, path, oflag) + __rtdm_dev_kopen(path, oflag) #define rt_dev_socket(protocol_family, socket_type, protocol) \ - __rt_dev_socket(&__xnsys_global_ppd, -1, protocol_family, socket_type, protocol) + __rtdm_dev_ksocket(protocol_family, socket_type, protocol) #define rt_dev_close(fd) \ rtdm_fd_close(&__xnsys_global_ppd, fd, RTDM_FD_MAGIC) diff --git a/kernel/cobalt/posix/io.c b/kernel/cobalt/posix/io.c index be58bd6..197d327 100644 --- a/kernel/cobalt/posix/io.c +++ b/kernel/cobalt/posix/io.c @@ -18,10 +18,7 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <linux/err.h> -#include <linux/file.h> #include <linux/fs.h> -#include <linux/fdtable.h> -#include <linux/anon_inodes.h> #include <cobalt/kernel/ppd.h> #include <xenomai/rtdm/internal.h> #include "process.h" @@ -32,76 +29,24 @@ COBALT_SYSCALL(open, lostage, int, (const char __user *u_path, int oflag)) { - struct rtdm_device *device; struct filename *filename; - struct xnsys_ppd *ppd; - struct file *filp; - int ufd, ret; + int ufd; filename = getname(u_path); if (IS_ERR(filename)) return PTR_ERR(filename); - /* - * Lookup for the device into the RTDM registry: if we don't - * own the device, tell userland to forward to the regular - * open() service. - */ - device = __rtdm_get_namedev(filename->name); - if (device == NULL) { - ret = -ENODEV; - goto fail; - } - /* __rt_dev_open() will revalidate. */ - __rtdm_put_device(device); - - ufd = get_unused_fd_flags(oflag); - if (ufd < 0) { - ret = ufd; - goto fail; - } - - filp = filp_open(filename->name, oflag, 0); - if (IS_ERR(filp)) { - ret = PTR_ERR(filp); - goto fail_fopen; - } - - ppd = cobalt_ppd_get(0); - ret = __rt_dev_open(ppd, ufd, filename->name, oflag); - if (ret < 0) - goto fail_devopen; - - fd_install(ufd, filp); + ufd = __rtdm_dev_open(filename->name, oflag); putname(filename); return ufd; -fail_devopen: - filp_close(filp, current->files); -fail_fopen: - put_unused_fd(ufd); -fail: - putname(filename); - - return ret; } COBALT_SYSCALL(socket, lostage, int, (int protocol_family, int socket_type, int protocol)) { - struct xnsys_ppd *ppd; - int ufd, ret; - - ppd = cobalt_ppd_get(0); - ufd = anon_inode_getfd("[rtdm-proto]", &rtdm_dumb_fops, ppd, O_RDWR); - - ret = __rt_dev_socket(cobalt_ppd_get(0), ufd, - protocol_family, socket_type, protocol); - if (ret < 0) - __close_fd(current->files, ufd); - - return ret; + return __rtdm_dev_socket(protocol_family, socket_type, protocol); } COBALT_SYSCALL(close, lostage, int, (int fd)) diff --git a/kernel/cobalt/rtdm/core.c b/kernel/cobalt/rtdm/core.c index 5e05b30..9028652 100644 --- a/kernel/cobalt/rtdm/core.c +++ b/kernel/cobalt/rtdm/core.c @@ -18,12 +18,17 @@ */ #include <linux/workqueue.h> #include <linux/slab.h> +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/fdtable.h> +#include <linux/anon_inodes.h> #include <cobalt/kernel/ppd.h> #include <cobalt/kernel/heap.h> #include <cobalt/kernel/apc.h> #include "rtdm/internal.h" #define CREATE_TRACE_POINTS #include <trace/events/cobalt-rtdm.h> +#include "posix/process.h" /** * @ingroup rtdm @@ -72,14 +77,13 @@ void __rt_dev_unref(struct rtdm_fd *fd, unsigned int idx) xnlock_put(&rt_fildes_lock); } -static int create_instance(struct xnsys_ppd *p, int fd, - struct rtdm_device *device, - struct rtdm_dev_context **context_ptr) +static int create_kinstance(struct rtdm_device *device, + struct rtdm_dev_context **context_ptr) { struct rtdm_device_class *class = device->class; struct rtdm_dev_context *context; + int ufd, ret; spl_t s; - int ret; /* * Reset to NULL so that we can always use cleanup_files/instance to @@ -87,21 +91,19 @@ static int create_instance(struct xnsys_ppd *p, int fd, */ *context_ptr = NULL; - if (p == &__xnsys_global_ppd) { - xnlock_get_irqsave(&rt_fildes_lock, s); - - if (unlikely(open_fildes >= RTDM_FD_MAX)) { - xnlock_put_irqrestore(&rt_fildes_lock, s); - return -ENFILE; - } - - fd = find_first_zero_bit(used_fildes, RTDM_FD_MAX); - __set_bit(fd, used_fildes); - open_fildes++; + xnlock_get_irqsave(&rt_fildes_lock, s); + if (unlikely(open_fildes >= RTDM_FD_MAX)) { xnlock_put_irqrestore(&rt_fildes_lock, s); + return -ENFILE; } + ufd = find_first_zero_bit(used_fildes, RTDM_FD_MAX); + __set_bit(ufd, used_fildes); + open_fildes++; + + xnlock_put_irqrestore(&rt_fildes_lock, s); + if ((class->device_flags & RTDM_EXCLUSIVE) != 0 && atomic_read(&device->refcount) > 1) { ret = -EBUSY; @@ -118,37 +120,116 @@ static int create_instance(struct xnsys_ppd *p, int fd, context->device = device; *context_ptr = context; - ret = rtdm_fd_enter(p, &context->fd, fd, RTDM_FD_MAGIC, &device->ops); + ret = rtdm_fd_enter(&__xnsys_global_ppd, &context->fd, ufd, + RTDM_FD_MAGIC, &device->ops); if (ret < 0) goto fail; - return fd; + return ufd; fail: - if (p == &__xnsys_global_ppd) { - xnlock_get_irqsave(&rt_fildes_lock, s); - __clear_bit(fd, used_fildes); - open_fildes--; - xnlock_put_irqrestore(&rt_fildes_lock, s); + xnlock_get_irqsave(&rt_fildes_lock, s); + __clear_bit(ufd, used_fildes); + open_fildes--; + xnlock_put_irqrestore(&rt_fildes_lock, s); + + return ret; +} + +static int create_instance(struct xnsys_ppd *ppd, int ufd, + struct rtdm_device *device, + struct rtdm_dev_context **context_ptr) +{ + struct rtdm_device_class *class = device->class; + struct rtdm_dev_context *context; + + /* + * Reset to NULL so that we can always use cleanup_files/instance to + * revert also partially successful allocations. + */ + *context_ptr = NULL; + + if ((class->device_flags & RTDM_EXCLUSIVE) != 0 && + atomic_read(&device->refcount) > 1) + return -EBUSY; + + context = kmalloc(sizeof(struct rtdm_dev_context) + + class->context_size, GFP_KERNEL); + if (unlikely(context == NULL)) + return -ENOMEM; + + context->device = device; + *context_ptr = context; + + return rtdm_fd_enter(ppd, &context->fd, ufd, RTDM_FD_MAGIC, &device->ops); +} + +int __rtdm_dev_kopen(const char *path, int oflag) +{ + struct rtdm_dev_context *context; + struct rtdm_device *device; + int ufd, ret; + + device = __rtdm_get_namedev(path); + if (device == NULL) + return -ENODEV; + + ufd = create_kinstance(device, &context); + if (ufd < 0) { + ret = ufd; + goto fail; + } + + context->fd.minor = device->minor; + + trace_cobalt_fd_open(current, &context->fd, ufd, oflag); + + if (device->ops.open) { + ret = device->ops.open(&context->fd, oflag); + if (!XENO_ASSERT(COBALT, !spltest())) + splnone(); + if (ret < 0) + goto fail; } + trace_cobalt_fd_created(&context->fd, ufd); + + return ufd; +fail: + cleanup_instance(device, context); + return ret; } +EXPORT_SYMBOL_GPL(__rtdm_dev_kopen); -int __rt_dev_open(struct xnsys_ppd *p, int ufd, const char *path, int oflag) +int __rtdm_dev_open(const char *path, int oflag) { struct rtdm_dev_context *context; struct rtdm_device *device; - int ret; + struct xnsys_ppd *ppd; + struct file *filp; + int ufd, ret; device = __rtdm_get_namedev(path); if (device == NULL) return -ENODEV; - ret = create_instance(p, ufd, device, &context); + ufd = get_unused_fd_flags(oflag); + if (ufd < 0) { + ret = ufd; + goto fail_fd; + } + + filp = filp_open(path, oflag, 0); + if (IS_ERR(filp)) { + ret = PTR_ERR(filp); + goto fail_fopen; + } + + ppd = cobalt_ppd_get(0); + ret = create_instance(ppd, ufd, device, &context); if (ret < 0) - goto cleanup_out; + goto fail_create; - ufd = ret; context->fd.minor = device->minor; trace_cobalt_fd_open(current, &context->fd, ufd, oflag); @@ -158,35 +239,87 @@ int __rt_dev_open(struct xnsys_ppd *p, int ufd, const char *path, int oflag) if (!XENO_ASSERT(COBALT, !spltest())) splnone(); if (ret < 0) - goto cleanup_out; + goto fail_open; } + fd_install(ufd, filp); + trace_cobalt_fd_created(&context->fd, ufd); return ufd; -cleanup_out: +fail_open: cleanup_instance(device, context); +fail_create: + filp_close(filp, current->files); +fail_fopen: + put_unused_fd(ufd); +fail_fd: + __rtdm_put_device(device); return ret; } -EXPORT_SYMBOL_GPL(__rt_dev_open); +EXPORT_SYMBOL_GPL(__rtdm_dev_open); -int __rt_dev_socket(struct xnsys_ppd *p, int ufd, int protocol_family, - int socket_type, int protocol) +int __rtdm_dev_ksocket(int protocol_family, int socket_type, + int protocol) { struct rtdm_dev_context *context; struct rtdm_device *device; - int ret; + int ufd, ret; device = __rtdm_get_protodev(protocol_family, socket_type); if (device == NULL) return -EAFNOSUPPORT; - ret = create_instance(p, ufd, device, &context); + ufd = create_kinstance(device, &context); + if (ufd < 0) { + ret = ufd; + goto fail; + } + + trace_cobalt_fd_socket(current, &context->fd, ufd, protocol_family); + + if (device->ops.socket) { + ret = device->ops.socket(&context->fd, protocol); + if (!XENO_ASSERT(COBALT, !spltest())) + splnone(); + if (ret < 0) + goto fail; + } + + trace_cobalt_fd_created(&context->fd, ufd); + + return ufd; +fail: + cleanup_instance(device, context); + + return ret; +} +EXPORT_SYMBOL_GPL(__rtdm_dev_ksocket); + +int __rtdm_dev_socket(int protocol_family, int socket_type, + int protocol) +{ + struct rtdm_dev_context *context; + struct rtdm_device *device; + struct xnsys_ppd *ppd; + int ufd, ret; + + device = __rtdm_get_protodev(protocol_family, socket_type); + if (device == NULL) + return -EAFNOSUPPORT; + + ppd = cobalt_ppd_get(0); + ufd = anon_inode_getfd("[rtdm-proto]", &rtdm_dumb_fops, ppd, O_RDWR); + if (ufd < 0) { + ret = ufd; + goto fail_getfd; + } + + ret = create_instance(ppd, ufd, device, &context); if (ret < 0) - goto cleanup_out; - ufd = ret; + goto fail_create; trace_cobalt_fd_socket(current, &context->fd, ufd, protocol_family); @@ -195,19 +328,23 @@ int __rt_dev_socket(struct xnsys_ppd *p, int ufd, int protocol_family, if (!XENO_ASSERT(COBALT, !spltest())) splnone(); if (ret < 0) - goto cleanup_out; + goto fail_socket; } trace_cobalt_fd_created(&context->fd, ufd); return ufd; -cleanup_out: +fail_socket: cleanup_instance(device, context); +fail_create: + __close_fd(current->files, ufd); +fail_getfd: + __rtdm_put_device(device); return ret; } -EXPORT_SYMBOL_GPL(__rt_dev_socket); +EXPORT_SYMBOL_GPL(__rtdm_dev_socket); int __rt_dev_ioctl_fallback(struct rtdm_fd *fd, unsigned int request, void __user *arg) diff --git a/kernel/cobalt/rtdm/internal.h b/kernel/cobalt/rtdm/internal.h index 7d52275..016f567 100644 --- a/kernel/cobalt/rtdm/internal.h +++ b/kernel/cobalt/rtdm/internal.h @@ -50,6 +50,16 @@ static inline void __rtdm_get_device(struct rtdm_device *device) void __rtdm_put_device(struct rtdm_device *device); +int __rtdm_dev_open(const char *path, int oflag); + +int __rtdm_dev_socket(int protocol_family, + int socket_type, int protocol); + +struct rtdm_device *__rtdm_get_namedev(const char *path); + +struct rtdm_device *__rtdm_get_protodev(int protocol_family, + int socket_type); + void __rt_dev_close(struct rtdm_fd *fd); int __rt_dev_ioctl_fallback(struct rtdm_fd *fd, @@ -60,10 +70,6 @@ void __rt_dev_unref(struct rtdm_fd *fd, unsigned int idx); int __rtdm_mmap_from_fdop(struct rtdm_fd *fd, size_t len, off_t offset, int prot, int flags, void *__user *pptr); -struct rtdm_device *__rtdm_get_namedev(const char *path); - -struct rtdm_device *__rtdm_get_protodev(int protocol_family, int socket_type); - int rtdm_init(void); void rtdm_cleanup(void); _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git