[OpenWrt-Devel] [PATCH 3/3] kernel: trelay: log "started" and "stopped"
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
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
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