[OpenWrt-Devel] [PATCH 3/3] kernel: trelay: log "started" and "stopped"

2019-09-25 Thread Ali MJ Al-Nasrawy
It is informative especially when using multiple device pairs.

Signed-off-by: Ali MJ Al-Nasrawy 
---
 package/kernel/trelay/src/trelay.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/package/kernel/trelay/src/trelay.c 
b/package/kernel/trelay/src/trelay.c
index 0e3d85bfef..4c1cf706d7 100644
--- a/package/kernel/trelay/src/trelay.c
+++ b/package/kernel/trelay/src/trelay.c
@@ -20,6 +20,10 @@
 #include 
 #include 
 
+#define trelay_log(loglevel, tr, fmt, ...) \
+   printk(loglevel "trelay: %s <-> %s: " fmt "\n", \
+   tr->dev1->name, tr->dev2->name, ##__VA_ARGS__);
+
 static LIST_HEAD(trelay_devs);
 static struct dentry *debugfs_dir;
 
@@ -71,6 +75,8 @@ static int trelay_do_remove(struct trelay *tr)
netdev_rx_handler_unregister(tr->dev1);
netdev_rx_handler_unregister(tr->dev2);
 
+   trelay_log(KERN_INFO, tr, "stopped");
+
kfree(tr);
 
return 0;
@@ -183,6 +189,8 @@ static int trelay_do_add(char *name, char *devn1, char 
*devn2)
tr->dev2 = dev2;
list_add_tail(>list, _devs);
 
+   trelay_log(KERN_INFO, tr, "started");
+
tr->debugfs = debugfs_create_dir(name, debugfs_dir);
debugfs_create_file("remove", S_IWUSR, tr->debugfs, tr, _remove);
ret = 0;
-- 
2.23.0


___
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel


[OpenWrt-Devel] [PATCH 2/3] kernel: trelay: fix deadlock on remove

2019-09-25 Thread Ali MJ Al-Nasrawy
Upon writing to "remove" file, debugfs_remove_recursive() blocks while
holding rtnl_lock. This is because debugfs' file_ops callbacks are
executed in debugfs_use_file_*() context which prevents file removal.

Fix this by only flagging the device for removal and then do the cleanup
in file_ops.release callback which is executed out of that context.

Signed-off-by: Ali MJ Al-Nasrawy 
---
 package/kernel/trelay/src/trelay.c | 32 +-
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/package/kernel/trelay/src/trelay.c 
b/package/kernel/trelay/src/trelay.c
index 6d9d9cc14b..0e3d85bfef 100644
--- a/package/kernel/trelay/src/trelay.c
+++ b/package/kernel/trelay/src/trelay.c
@@ -27,6 +27,7 @@ struct trelay {
struct list_head list;
struct net_device *dev1, *dev2;
struct dentry *debugfs;
+   int to_remove;
char name[];
 };
 
@@ -60,13 +61,16 @@ static int trelay_do_remove(struct trelay *tr)
 {
list_del(>list);
 
+   /* First and before all, ensure that the debugfs file is removed
+* to prevent dangling pointer in file->private_data */
+   debugfs_remove_recursive(tr->debugfs);
+
dev_put(tr->dev1);
dev_put(tr->dev2);
 
netdev_rx_handler_unregister(tr->dev1);
netdev_rx_handler_unregister(tr->dev2);
 
-   debugfs_remove_recursive(tr->debugfs);
kfree(tr);
 
return 0;
@@ -106,23 +110,33 @@ static ssize_t trelay_remove_write(struct file *file, 
const char __user *ubuf,
   size_t count, loff_t *ppos)
 {
struct trelay *tr = file->private_data;
-   int ret;
-
-   rtnl_lock();
-   ret = trelay_do_remove(tr);
-   rtnl_unlock();
-
-   if (ret < 0)
-return ret;
+   tr->to_remove = 1;
 
return count;
 }
 
+static int trelay_remove_release(struct inode *inode, struct file *file)
+{
+   struct trelay *tr, *tmp;
+
+   /* This is the only file op that is called outside debugfs_use_file_*()
+* context which means that: (1) this file can be removed and
+* (2) file->private_data may no longer be valid */
+   rtnl_lock();
+   list_for_each_entry_safe(tr, tmp, _devs, list)
+   if (tr->to_remove)
+   trelay_do_remove(tr);
+   rtnl_unlock();
+
+   return 0;
+}
+
 static const struct file_operations fops_remove = {
.owner = THIS_MODULE,
.open = trelay_open,
.write = trelay_remove_write,
.llseek = default_llseek,
+   .release = trelay_remove_release,
 };
 
 
-- 
2.23.0


___
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel


[OpenWrt-Devel] [PATCH 1/3] kernel: trelay: handle netdevice events correctly

2019-09-25 Thread Ali MJ Al-Nasrawy
Since v3.11, netdevice notification data are of type
"struct netdev_notifier_info". Handle it as such!

This should fix a critical bug in which devices are unable get released
because trelay does not release resources in response to UNREGISTER
event spamming the log with something like:

unregister_netdevice: waiting for eth0.1 to become free. Usage count = 1

Signed-off-by: Ali MJ Al-Nasrawy 
---
 package/kernel/trelay/src/trelay.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package/kernel/trelay/src/trelay.c 
b/package/kernel/trelay/src/trelay.c
index 581a5cfd2f..6d9d9cc14b 100644
--- a/package/kernel/trelay/src/trelay.c
+++ b/package/kernel/trelay/src/trelay.c
@@ -86,7 +86,7 @@ static struct trelay *trelay_find(struct net_device *dev)
 static int tr_device_event(struct notifier_block *unused, unsigned long event,
   void *ptr)
 {
-   struct net_device *dev = ptr;
+   struct net_device *dev = ((struct netdev_notifier_info *)ptr)->dev;
struct trelay *tr;
 
if (event != NETDEV_UNREGISTER)
-- 
2.23.0


___
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel