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

Reply via email to