devices/rtdmnet.c : abuse RTDM api to allow sendmsg and recvmsg to be called indirectly from userland cobalt process ioctl, while rtdm_socket is created from a kernel thread. stable-1.5
authorEdouard Tisserant <edouard.tisserant@gmail.com>
Mon, 08 Oct 2018 23:16:34 +0200
branchstable-1.5
changeset 2726 ca80d6dac4c8
parent 2725 e008dc9d8c9f
child 2727 32c9a2dea9ed
devices/rtdmnet.c : abuse RTDM api to allow sendmsg and recvmsg to be called indirectly from userland cobalt process ioctl, while rtdm_socket is created from a kernel thread.
devices/rtdmnet.c
--- a/devices/rtdmnet.c	Sun Oct 07 17:05:42 2018 +0200
+++ b/devices/rtdmnet.c	Mon Oct 08 23:16:34 2018 +0200
@@ -80,6 +80,7 @@
     struct net_device *netdev;
     struct rtnet_device *used_netdev;
     int socket;
+    struct rtdm_fd *rtdm_fd;
     ec_device_t *ecdev;
     uint8_t *rx_buf;
     // struct sockaddr_ll dest_addr;
@@ -195,6 +196,7 @@
         ecdev_withdraw(dev->ecdev);
     }
     if (!(dev->socket < 0)) {
+        rtdm_fd_put(dev->rtdm_fd);
         rtdm_close(dev->socket);
         dev->socket = -1;
     }
@@ -228,6 +230,24 @@
         printk(" rtdm_socket() = %d!\n", dev->socket);
         return dev->socket;
     }
+    
+    /* HACK :
+       When this is called, process is 'kernel', i.e. 
+         cobalt_ppd_get(0) == &cobalt_kernel_ppd
+
+       This makes a problem later when recvmsg or sendmsg is indirectly called
+       from application's cobalt thread through RTDM IOCTL. From such thread, 
+       RTDM can't resolv socket's 'ufd' that rtdm_socket just returned.
+
+       To keep a usable file descriptor for that socket, even when calling 
+       from cobalt thread (i.e. if (cobalt_ppd_get(0) != &cobalt_kernel_ppd))
+       we resolve it here in advance */
+    dev->rtdm_fd = rtdm_fd_get(dev->socket,0);
+	if (IS_ERR(dev->rtdm_fd)){
+        printk(" rtdm_fd_get() = %d!\n", ret);
+		ret = PTR_ERR(dev->rtdm_fd);
+        goto out_err;
+    }
 
     printk(KERN_ERR PFX "Binding socket to interface %i (%s).\n",
             desc->ifindex, desc->name);
@@ -240,12 +260,17 @@
                       sizeof(struct sockaddr_ll));
     if (ret < 0) {
         printk(" rtdm_bind() = %d!\n", ret);
-        rtdm_close(dev->socket);
-        dev->socket = -1;
-        return ret;
+        goto out_err;
     }
 
     return 0;
+
+out_err:
+    rtdm_fd_put(dev->rtdm_fd);
+    rtdm_close(dev->socket);
+    dev->socket = -1;
+    return ret;
+    
 }
 
 /*****************************************************************************/
@@ -351,7 +376,8 @@
     msg.msg_iovlen  = 1;
 
 	if (rtdm_in_rt_context())
-        ret = rtdm_sendmsg(dev->socket, &msg, 0);
+        /* HACK : call fd ops directly as in rtdm's fd.c */
+        ret = dev->rtdm_fd->ops->sendmsg_rt(dev->rtdm_fd, &msg, 0);
 	else
         ret = nrt_rtdm_sendmsg(dev->socket, &msg);
 
@@ -406,9 +432,10 @@
         msg.msg_iov     = &iov;
         msg.msg_iovlen  = 1;
 
-        if (rtdm_in_rt_context())
-            ret = rtdm_recvmsg(dev->socket, &msg, MSG_DONTWAIT);
-        else
+        if (rtdm_in_rt_context()){
+            /* HACK : call fd ops directly as in rtdm's fd.c */
+            ret = dev->rtdm_fd->ops->recvmsg_rt(dev->rtdm_fd, &msg, MSG_DONTWAIT);
+        }else
             ret = nrt_rtdm_recvmsg(dev->socket, &msg);
 
         if (ret > 0) {