From: Linus Lüssing linus.luessing@web.de
hardif_remove_interfaces() removes all hard interfaces from the hardif_list before freeing and cleaning up any device. However the clean up procedures in orig_hash_del_if() (hardif_remove_interface()->hardif_disable_interface()-> orig_hash_del_if()) need the other interfaces still to be present in the hardif_list. Otherwise it won't renumber any preceding interfaces, which leads to an unhandled kernel paging request in orig_node_del_if()'s "/* copy second part */" due to wrong hard_if->if_num's.
With this commit the interface removal on module shutdown will be down in the same way as removing single interfaces from batman only: One interface will be removed and cleaned at a time.
Signed-off-by: Linus Lüssing linus.luessing@web.de [sven@narfation.org: Keep locking around list_for_each_entry_safe] Signed-off-by: Sven Eckelmann sven@narfation.org --- Splitted the first patch to keep Linus' fame. There should be no difference (after all patches are applied) between the first and the second version.
hard-interface.c | 11 ++--------- 1 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/hard-interface.c b/hard-interface.c index b3058e4..c6edf0a 100644 --- a/hard-interface.c +++ b/hard-interface.c @@ -490,22 +490,15 @@ static void hardif_remove_interface(struct hard_iface *hard_iface) void hardif_remove_interfaces(void) { struct hard_iface *hard_iface, *hard_iface_tmp; - struct list_head if_queue; - - INIT_LIST_HEAD(&if_queue);
+ rtnl_lock(); spin_lock(&hardif_list_lock); list_for_each_entry_safe(hard_iface, hard_iface_tmp, &hardif_list, list) { list_del_rcu(&hard_iface->list); - list_add_tail(&hard_iface->list, &if_queue); - } - spin_unlock(&hardif_list_lock); - - rtnl_lock(); - list_for_each_entry_safe(hard_iface, hard_iface_tmp, &if_queue, list) { hardif_remove_interface(hard_iface); } + spin_unlock(&hardif_list_lock); rtnl_unlock(); }