Module: xenomai-gch
Branch: for-forge
Commit: 6984953d1864a765c871f233122873bc3a356867
URL:    
http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=6984953d1864a765c871f233122873bc3a356867

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Tue Sep 29 23:17:18 2015 +0200

rtnet/socket: rework reference counting

With socket pools allocations locking sockets, when a received packet
switches from the device pool to the socket pool and is queued in a
socket incoming queue, the socket is locked preventing its destruction
until all packets have been received. This is probably the reason for
this bug report:
http://xenomai.org/pipermail/xenomai/2015-June/034345.html

Furthermore, when looking at the code in af_packet.c, udp.c or tcp.c,
when a packet has been acquired by the socket pool, but is not yet
queued, the socket is locked, so, the socket can not disappear and the
packet leak, so the locking is redundant.

What can happen however, is that a module can be removed in the middle
of the packet reception, causing all sorts of trouble.

So, this commit:
- suppresses the locking of sockets by the socket pool allocation;
- gets sockets creation to lock the module in which they are created.

---

 kernel/drivers/net/stack/include/rtnet_socket.h |   16 +++++--
 kernel/drivers/net/stack/ipv4/icmp.c            |    8 ++--
 kernel/drivers/net/stack/rtmac/rtmac_vnic.c     |   17 +------
 kernel/drivers/net/stack/rtskb.c                |   17 ++++++-
 kernel/drivers/net/stack/socket.c               |   58 +++++++++++------------
 5 files changed, 62 insertions(+), 54 deletions(-)

diff --git a/kernel/drivers/net/stack/include/rtnet_socket.h 
b/kernel/drivers/net/stack/include/rtnet_socket.h
index 363267e..4de05d5 100644
--- a/kernel/drivers/net/stack/include/rtnet_socket.h
+++ b/kernel/drivers/net/stack/include/rtnet_socket.h
@@ -78,6 +78,8 @@ struct rtsocket {
            int                  ifindex;
        } packet;
     } prot;
+
+    struct module *module;
 };
 
 
@@ -91,7 +93,11 @@ static inline struct rtdm_fd *rt_socket_fd(struct rtsocket 
*sock)
 #define rt_socket_dereference(sock) \
     rtdm_fd_unlock(rt_socket_fd(sock))
 
-int rt_socket_init(struct rtdm_fd *fd, unsigned short protocol);
+int __rt_socket_init(struct rtdm_fd *fd, unsigned short protocol,
+               struct module *module);
+#define rt_socket_init(fd, proto) \
+    __rt_socket_init(fd, proto, THIS_MODULE)
+
 void rt_socket_cleanup(struct rtdm_fd *fd);
 int rt_socket_common_ioctl(struct rtdm_fd *fd, int request, void *arg);
 int rt_socket_if_ioctl(struct rtdm_fd *fd, int request, void *arg);
@@ -100,12 +106,16 @@ int rt_socket_select_bind(struct rtdm_fd *fd,
                          enum rtdm_selecttype type,
                          unsigned fd_index);
 
-int rt_bare_socket_init(struct rtdm_fd *fd, unsigned short protocol,
-                       unsigned int priority, unsigned int pool_size);
+int __rt_bare_socket_init(struct rtdm_fd *fd, unsigned short protocol,
+                       unsigned int priority, unsigned int pool_size,
+                       struct module *module);
+#define rt_bare_socket_init(fd, proto, prio, pool_sz) \
+    __rt_bare_socket_init(fd, proto, prio, pool_sz, THIS_MODULE)
 
 static inline void rt_bare_socket_cleanup(struct rtsocket *sock)
 {
     rtskb_pool_release(&sock->skb_pool);
+    module_put(sock->module);
 }
 
 #endif  /* __RTNET_SOCKET_H_ */
diff --git a/kernel/drivers/net/stack/ipv4/icmp.c 
b/kernel/drivers/net/stack/ipv4/icmp.c
index b6ae736..58d97cd 100644
--- a/kernel/drivers/net/stack/ipv4/icmp.c
+++ b/kernel/drivers/net/stack/ipv4/icmp.c
@@ -524,11 +524,11 @@ static struct rtinet_protocol icmp_protocol = {
  */
 void __init rt_icmp_init(void)
 {
-    unsigned int skbs;
+    int skbs;
 
-
-    skbs = rt_bare_socket_init(icmp_fd, IPPROTO_ICMP, RT_ICMP_PRIO,
-                           ICMP_REPLY_POOL_SIZE);
+    skbs = __rt_bare_socket_init(icmp_fd, IPPROTO_ICMP, RT_ICMP_PRIO,
+                           ICMP_REPLY_POOL_SIZE, NULL);
+    BUG_ON(skbs < 0);
     if (skbs < ICMP_REPLY_POOL_SIZE)
        printk("RTnet: allocated only %d icmp rtskbs\n", skbs);
 
diff --git a/kernel/drivers/net/stack/rtmac/rtmac_vnic.c 
b/kernel/drivers/net/stack/rtmac/rtmac_vnic.c
index e17405e..510e714 100644
--- a/kernel/drivers/net/stack/rtmac/rtmac_vnic.c
+++ b/kernel/drivers/net/stack/rtmac/rtmac_vnic.c
@@ -231,20 +231,6 @@ static void rtmac_vnic_setup(struct net_device *dev)
     dev->flags           &= ~IFF_MULTICAST;
 }
 
-static int rtmac_vnic_pool_trylock(void *cookie)
-{
-    return 1;
-}
-
-static void rtmac_vnic_pool_unlock(void *cookie)
-{
-}
-
-static const struct rtskb_pool_lock_ops rtmac_vnic_pool_lock_ops = {
-    .trylock = rtmac_vnic_pool_trylock,
-    .unlock = rtmac_vnic_pool_unlock,
-};
-
 int rtmac_vnic_add(struct rtnet_device *rtdev, vnic_xmit_handler vnic_xmit)
 {
     int                 res;
@@ -263,8 +249,7 @@ int rtmac_vnic_add(struct rtnet_device *rtdev, 
vnic_xmit_handler vnic_xmit)
 
     /* create the rtskb pool */
     if (rtskb_pool_init(&mac_priv->vnic_skb_pool,
-                           vnic_rtskbs, &rtmac_vnic_pool_lock_ops,
-                           NULL) < vnic_rtskbs) {
+                           vnic_rtskbs, NULL, NULL) < vnic_rtskbs) {
        res = -ENOMEM;
        goto error;
     }
diff --git a/kernel/drivers/net/stack/rtskb.c b/kernel/drivers/net/stack/rtskb.c
index 23d6332..8afd6a6 100644
--- a/kernel/drivers/net/stack/rtskb.c
+++ b/kernel/drivers/net/stack/rtskb.c
@@ -295,6 +295,21 @@ void kfree_rtskb(struct rtskb *skb)
 EXPORT_SYMBOL_GPL(kfree_rtskb);
 
 
+static int rtskb_nop_pool_trylock(void *cookie)
+{
+    return 1;
+}
+
+static void rtskb_nop_pool_unlock(void *cookie)
+{
+}
+
+static const struct rtskb_pool_lock_ops rtskb_nop_pool_lock_ops = {
+    .trylock = rtskb_nop_pool_trylock,
+    .unlock = rtskb_nop_pool_unlock,
+};
+
+
 /***
  *  rtskb_pool_init
  *  @pool: pool to be initialized
@@ -316,7 +331,7 @@ unsigned int rtskb_pool_init(struct rtskb_pool *pool,
     if (rtskb_pools > rtskb_pools_max)
        rtskb_pools_max = rtskb_pools;
 
-    pool->lock_ops = lock_ops;
+    pool->lock_ops = lock_ops ?: &rtskb_nop_pool_lock_ops;
     pool->lock_count = 0;
     pool->lock_cookie = lock_cookie;
 
diff --git a/kernel/drivers/net/stack/socket.c 
b/kernel/drivers/net/stack/socket.c
index a38f560..9aee773 100644
--- a/kernel/drivers/net/stack/socket.c
+++ b/kernel/drivers/net/stack/socket.c
@@ -49,38 +49,36 @@ MODULE_PARM_DESC(socket_rtskbs, "Default number of realtime 
socket buffers in so
  *  internal socket functions                                           *
  ************************************************************************/
 
-static int rtskb_socket_pool_trylock(void *cookie)
+int __rt_bare_socket_init(struct rtdm_fd *fd, unsigned short protocol,
+                       unsigned int priority, unsigned int pool_size,
+                       struct module *module)
 {
-    return rtdm_fd_lock(cookie) >= 0;
-}
+    struct rtsocket *sock = rtdm_fd_to_private(fd);
+    int err;
 
-static void rtskb_socket_pool_unlock(void *cookie)
-{
-    rtdm_fd_unlock(cookie);
-}
+    err = try_module_get(module);
+    if (!err)
+       return -EAFNOSUPPORT;
 
-static const struct rtskb_pool_lock_ops rtskb_socket_pool_ops = {
-    .trylock = rtskb_socket_pool_trylock,
-    .unlock = rtskb_socket_pool_unlock,
-};
+    err = rtskb_pool_init(&sock->skb_pool, pool_size, NULL, fd);
+    if (err < 0) {
+       module_put(module);
+       return err;
+    }
 
-int rt_bare_socket_init(struct rtdm_fd *fd,
-                       unsigned short protocol,
-                       unsigned int priority, unsigned int pool_size)
-{
-    struct rtsocket *sock = rtdm_fd_to_private(fd);
     sock->protocol = protocol;
     sock->priority = priority;
+    sock->module = module;
 
-    return rtskb_pool_init(&sock->skb_pool,
-                       pool_size, &rtskb_socket_pool_ops, fd);
+    return err;
 }
-EXPORT_SYMBOL_GPL(rt_bare_socket_init);
+EXPORT_SYMBOL_GPL(__rt_bare_socket_init);
 
 /***
  *  rt_socket_init - initialises a new socket structure
  */
-int rt_socket_init(struct rtdm_fd *fd, unsigned short protocol)
+int __rt_socket_init(struct rtdm_fd *fd, unsigned short protocol,
+               struct module *module)
 {
     struct rtsocket *sock = rtdm_fd_to_private(fd);
     unsigned int    pool_size;
@@ -95,9 +93,10 @@ int rt_socket_init(struct rtdm_fd *fd, unsigned short 
protocol)
     rtdm_lock_init(&sock->param_lock);
     rtdm_sem_init(&sock->pending_sem, 0);
 
-    pool_size = rt_bare_socket_init(fd, protocol,
-               RTSKB_PRIO_VALUE(SOCK_DEF_PRIO,
-                               RTSKB_DEF_RT_CHANNEL), socket_rtskbs);
+    pool_size = __rt_bare_socket_init(fd, protocol,
+                                   RTSKB_PRIO_VALUE(SOCK_DEF_PRIO,
+                                                   RTSKB_DEF_RT_CHANNEL),
+                                   socket_rtskbs, module);
     sock->pool_size = pool_size;
     mutex_init(&sock->pool_nrt_lock);
 
@@ -112,7 +111,7 @@ int rt_socket_init(struct rtdm_fd *fd, unsigned short 
protocol)
 
     return 0;
 }
-
+EXPORT_SYMBOL_GPL(__rt_socket_init);
 
 
 /***
@@ -133,8 +132,10 @@ void rt_socket_cleanup(struct rtdm_fd *fd)
        rtskb_pool_release(&sock->skb_pool);
 
     mutex_unlock(&sock->pool_nrt_lock);
-}
 
+    module_put(sock->module);
+}
+EXPORT_SYMBOL_GPL(rt_socket_cleanup);
 
 
 /***
@@ -217,6 +218,7 @@ int rt_socket_common_ioctl(struct rtdm_fd *fd, int request, 
void *arg)
 
     return ret;
 }
+EXPORT_SYMBOL_GPL(rt_socket_common_ioctl);
 
 
 
@@ -313,6 +315,7 @@ int rt_socket_if_ioctl(struct rtdm_fd *fd, int request, 
void *arg)
     rtdev_dereference(rtdev);
     return ret;
 }
+EXPORT_SYMBOL_GPL(rt_socket_if_ioctl);
 
 
 int rt_socket_select_bind(struct rtdm_fd *fd,
@@ -332,9 +335,4 @@ int rt_socket_select_bind(struct rtdm_fd *fd,
 
     return -EINVAL;
 }
-
 EXPORT_SYMBOL_GPL(rt_socket_select_bind);
-EXPORT_SYMBOL_GPL(rt_socket_init);
-EXPORT_SYMBOL_GPL(rt_socket_cleanup);
-EXPORT_SYMBOL_GPL(rt_socket_common_ioctl);
-EXPORT_SYMBOL_GPL(rt_socket_if_ioctl);


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://xenomai.org/mailman/listinfo/xenomai-git

Reply via email to