Hi,
here are some smaller cleanup/bugfix patches for 2.6.37. All patches needed for that patchset are already part of your staging-next tree.
All patches are cleanup patches and no new feature is added.
thanks, Sven
Linus Lüssing (1): Staging: batman-adv: Always synchronize rcu's on module shutdown
Marek Lindner (1): Staging: batman-adv: removing redundant assignment of skb->dev
Sven Eckelmann (2): Staging: batman-adv: Remove currently unused gw_* datastructures Staging: batman-adv: Add rcu TODO
Vasiliy Kulikov (1): Staging: batman-adv: check kmalloc() return value
drivers/staging/batman-adv/TODO | 5 +++++ drivers/staging/batman-adv/main.c | 7 ++----- drivers/staging/batman-adv/routing.c | 8 ++++++-- drivers/staging/batman-adv/soft-interface.c | 5 +---- drivers/staging/batman-adv/types.h | 3 --- drivers/staging/batman-adv/unicast.c | 8 ++++++-- drivers/staging/batman-adv/unicast.h | 2 +- 7 files changed, 21 insertions(+), 17 deletions(-)
From: Linus Lüssing linus.luessing@web.de
During the module shutdown procedure in batman_exit(), a rcu callback is being scheduled (batman_exit -> hardif_remove_interfaces -> hardif_remove_interfae -> call_rcu). However, when the kernel unloads the module, the rcu callback might not have been executed yet, resulting in a "unable to handle kernel paging request" in __rcu_process_callback afterwards, causing the kernel to freeze.
The synchronize_net and synchronize_rcu in mesh_free are currently called before the call_rcu in hardif_remove_interface and have no real effect on it.
Therefore, we should always flush all rcu callback functions scheduled during the shutdown procedure using synchronize_net. The call to synchronize_rcu can be omitted because synchronize_net already calls it.
Signed-off-by: Linus Lüssing linus.luessing@web.de Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/main.c | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index 498861f..b3e23e1 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -71,6 +71,8 @@ static void __exit batman_exit(void) flush_workqueue(bat_event_workqueue); destroy_workqueue(bat_event_workqueue); bat_event_workqueue = NULL; + + synchronize_net(); }
int mesh_init(struct net_device *soft_iface) @@ -132,9 +134,6 @@ void mesh_free(struct net_device *soft_iface) hna_local_free(bat_priv); hna_global_free(bat_priv);
- synchronize_net(); - - synchronize_rcu(); atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); }
gw_list_lock, gw_list and curr_gw are currently unused members of struct bat_priv. They will be readded when gateway support is really implemented.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/main.c | 2 -- drivers/staging/batman-adv/types.h | 3 --- 2 files changed, 0 insertions(+), 5 deletions(-)
diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index b3e23e1..78ceebf 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -84,13 +84,11 @@ int mesh_init(struct net_device *soft_iface) spin_lock_init(&bat_priv->forw_bcast_list_lock); spin_lock_init(&bat_priv->hna_lhash_lock); spin_lock_init(&bat_priv->hna_ghash_lock); - spin_lock_init(&bat_priv->gw_list_lock); spin_lock_init(&bat_priv->vis_hash_lock); spin_lock_init(&bat_priv->vis_list_lock);
INIT_HLIST_HEAD(&bat_priv->forw_bat_list); INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); - INIT_HLIST_HEAD(&bat_priv->gw_list);
if (originator_init(bat_priv) < 1) goto err; diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index e779c4a..9d744d8 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -128,7 +128,6 @@ struct bat_priv { struct dentry *debug_dir; struct hlist_head forw_bat_list; struct hlist_head forw_bcast_list; - struct hlist_head gw_list; struct list_head vis_send_list; struct hashtable_t *orig_hash; struct hashtable_t *hna_local_hash; @@ -139,7 +138,6 @@ struct bat_priv { spinlock_t forw_bcast_list_lock; spinlock_t hna_lhash_lock; spinlock_t hna_ghash_lock; - spinlock_t gw_list_lock; spinlock_t vis_hash_lock; spinlock_t vis_list_lock; int16_t num_local_hna; @@ -147,7 +145,6 @@ struct bat_priv { struct delayed_work hna_work; struct delayed_work orig_work; struct delayed_work vis_work; - struct gw_node *curr_gw; struct vis_info *my_vis_info; };
Paul E. McKenney informed us that rcu is misused by leaking pointers to rcu related elements outside read-side protected critical sections.
He also recommended that it should be checked against the rcu checklist.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/TODO | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/staging/batman-adv/TODO b/drivers/staging/batman-adv/TODO index 1457c7f..3af8028 100644 --- a/drivers/staging/batman-adv/TODO +++ b/drivers/staging/batman-adv/TODO @@ -1,3 +1,8 @@ + * Rework usage of RCU + - don't leak pointers from rcu out of rcu critical area which may + get freed + - check were synchronize_rcu must be used + - go through Documentation/RCU/checklist.txt * Request a new review * Process the comments from the review * Move into mainline proper
From: Marek Lindner lindner_marek@yahoo.de
Signed-off-by: Marek Lindner lindner_marek@yahoo.de Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/soft-interface.c | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index 8d14343..3904db9 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -201,7 +201,7 @@ void interface_rx(struct net_device *soft_iface, skb_pull_rcsum(skb, hdr_size); /* skb_set_mac_header(skb, -sizeof(struct ethhdr));*/
- skb->dev = soft_iface; + /* skb->dev & skb->pkt_type are set here */ skb->protocol = eth_type_trans(skb, soft_iface);
/* should not be neccesary anymore as we use skb_pull_rcsum() @@ -210,9 +210,6 @@ void interface_rx(struct net_device *soft_iface,
/* skb->ip_summed = CHECKSUM_UNNECESSARY;*/
- /* TODO: set skb->pkt_type to PACKET_BROADCAST, PACKET_MULTICAST, - * PACKET_OTHERHOST or PACKET_HOST */ - priv->stats.rx_packets++; priv->stats.rx_bytes += skb->len + sizeof(struct ethhdr);
From: Vasiliy Kulikov segooon@gmail.com
kmalloc() may fail, if so drop current packet.
Signed-off-by: Vasiliy Kulikov segooon@gmail.com Signed-off-by: Marek Lindner lindner_marek@yahoo.de [sven.eckelmann@gmx.de: Removed new introduced deadlock] Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de --- drivers/staging/batman-adv/routing.c | 8 ++++++-- drivers/staging/batman-adv/unicast.c | 8 ++++++-- drivers/staging/batman-adv/unicast.h | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index e12fd99..2cf8cf9 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -1232,8 +1232,12 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if)
orig_node->last_frag_packet = jiffies;
- if (list_empty(&orig_node->frag_list)) - create_frag_buffer(&orig_node->frag_list); + if (list_empty(&orig_node->frag_list) && + create_frag_buffer(&orig_node->frag_list)) { + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, + flags); + return NET_RX_DROP; + }
tmp_frag_entry = search_frag_packet(&orig_node->frag_list, diff --git a/drivers/staging/batman-adv/unicast.c b/drivers/staging/batman-adv/unicast.c index f951abc..0dac50d 100644 --- a/drivers/staging/batman-adv/unicast.c +++ b/drivers/staging/batman-adv/unicast.c @@ -78,7 +78,7 @@ void create_frag_entry(struct list_head *head, struct sk_buff *skb) return; }
-void create_frag_buffer(struct list_head *head) +int create_frag_buffer(struct list_head *head) { int i; struct frag_packet_list_entry *tfp; @@ -86,13 +86,17 @@ void create_frag_buffer(struct list_head *head) for (i = 0; i < FRAG_BUFFER_SIZE; i++) { tfp = kmalloc(sizeof(struct frag_packet_list_entry), GFP_ATOMIC); + if (!tfp) { + frag_list_free(head); + return -ENOMEM; + } tfp->skb = NULL; tfp->seqno = 0; INIT_LIST_HEAD(&tfp->list); list_add(&tfp->list, head); }
- return; + return 0; }
struct frag_packet_list_entry *search_frag_packet(struct list_head *head, diff --git a/drivers/staging/batman-adv/unicast.h b/drivers/staging/batman-adv/unicast.h index 1d5cbeb..7973697 100644 --- a/drivers/staging/batman-adv/unicast.h +++ b/drivers/staging/batman-adv/unicast.h @@ -30,7 +30,7 @@ struct sk_buff *merge_frag_packet(struct list_head *head, struct sk_buff *skb);
void create_frag_entry(struct list_head *head, struct sk_buff *skb); -void create_frag_buffer(struct list_head *head); +int create_frag_buffer(struct list_head *head); struct frag_packet_list_entry *search_frag_packet(struct list_head *head, struct unicast_frag_packet *up); void frag_list_free(struct list_head *head);
b.a.t.m.a.n@lists.open-mesh.org