aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/name_table.c
diff options
context:
space:
mode:
authorErik Hugne <erik.hugne@ericsson.com>2014-03-06 08:40:20 -0500
committerDavid S. Miller <davem@davemloft.net>2014-03-06 14:46:24 -0500
commit1bb8dce57f4d15233688c68990852a10eb1cd79f (patch)
tree1ce55ec1541b24d7f6db65897067c7b7f637bcb2 /net/tipc/name_table.c
parentedcc0511b5ee7235282a688cd604e3ae7f9e1fc9 (diff)
tipc: fix memory leak during module removal
When the TIPC module is removed, the tasklet handler is disabled before all other subsystems. This will cause lingering publications in the name table because the node_down tasklets responsible to clean up publications from an unreachable node will never run. When the name table is shut down, these publications are detected and an error message is logged: tipc: nametbl_stop(): orphaned hash chain detected This is actually a memory leak, introduced with commit 993b858e37b3120ee76d9957a901cca22312ffaa ("tipc: correct the order of stopping services at rmmod") Instead of just logging an error and leaking memory, we free the orphaned entries during nametable shutdown. Signed-off-by: Erik Hugne <erik.hugne@ericsson.com> Reviewed-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/name_table.c')
-rw-r--r--net/tipc/name_table.c37
1 files changed, 34 insertions, 3 deletions
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 48302be175ce..042e8e3cabc0 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -941,17 +941,48 @@ int tipc_nametbl_init(void)
941 return 0; 941 return 0;
942} 942}
943 943
944/**
945 * tipc_purge_publications - remove all publications for a given type
946 *
947 * tipc_nametbl_lock must be held when calling this function
948 */
949static void tipc_purge_publications(struct name_seq *seq)
950{
951 struct publication *publ, *safe;
952 struct sub_seq *sseq;
953 struct name_info *info;
954
955 if (!seq->sseqs) {
956 nameseq_delete_empty(seq);
957 return;
958 }
959 sseq = seq->sseqs;
960 info = sseq->info;
961 list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) {
962 tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node,
963 publ->ref, publ->key);
964 }
965}
966
944void tipc_nametbl_stop(void) 967void tipc_nametbl_stop(void)
945{ 968{
946 u32 i; 969 u32 i;
970 struct name_seq *seq;
971 struct hlist_head *seq_head;
972 struct hlist_node *safe;
947 973
948 /* Verify name table is empty, then release it */ 974 /* Verify name table is empty and purge any lingering
975 * publications, then release the name table
976 */
949 write_lock_bh(&tipc_nametbl_lock); 977 write_lock_bh(&tipc_nametbl_lock);
950 for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { 978 for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {
951 if (hlist_empty(&table.types[i])) 979 if (hlist_empty(&table.types[i]))
952 continue; 980 continue;
953 pr_err("nametbl_stop(): orphaned hash chain detected\n"); 981 seq_head = &table.types[i];
954 break; 982 hlist_for_each_entry_safe(seq, safe, seq_head, ns_list) {
983 tipc_purge_publications(seq);
984 }
985 continue;
955 } 986 }
956 kfree(table.types); 987 kfree(table.types);
957 table.types = NULL; 988 table.types = NULL;