diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2008-05-07 11:47:01 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-21 21:47:42 -0400 |
commit | 4caf86c6928cfaca270327bc944f901c2e2a8f50 (patch) | |
tree | 6f6a1ecac1a4399c6597510f4076e19b1e30f10e | |
parent | 5194ee82b4aafc35b32c96db11bdacea9bf548be (diff) |
mac80211: Prepare mesh_table_grow to failing copy_node callback.
The mesh_path_node_copy() performs kmalloc() and thus - may fail
(well, it does not now, but I'm fixing this right now). Its caller -
the mesh_table_grow() - isn't prepared for such a trick yet.
This preparation is just flush the new hash and make copy_node()
return an int value.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | net/mac80211/mesh.c | 15 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 2 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 3 |
3 files changed, 16 insertions, 4 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 697ef67f96b6..ca81d0065eb8 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -349,7 +349,7 @@ struct mesh_table *mesh_table_grow(struct mesh_table *tbl) | |||
349 | { | 349 | { |
350 | struct mesh_table *newtbl; | 350 | struct mesh_table *newtbl; |
351 | struct hlist_head *oldhash; | 351 | struct hlist_head *oldhash; |
352 | struct hlist_node *p; | 352 | struct hlist_node *p, *q; |
353 | int err = 0; | 353 | int err = 0; |
354 | int i; | 354 | int i; |
355 | 355 | ||
@@ -373,13 +373,24 @@ struct mesh_table *mesh_table_grow(struct mesh_table *tbl) | |||
373 | oldhash = tbl->hash_buckets; | 373 | oldhash = tbl->hash_buckets; |
374 | for (i = 0; i <= tbl->hash_mask; i++) | 374 | for (i = 0; i <= tbl->hash_mask; i++) |
375 | hlist_for_each(p, &oldhash[i]) | 375 | hlist_for_each(p, &oldhash[i]) |
376 | tbl->copy_node(p, newtbl); | 376 | if (tbl->copy_node(p, newtbl) < 0) |
377 | goto errcopy; | ||
377 | 378 | ||
378 | endgrow: | 379 | endgrow: |
379 | if (err) | 380 | if (err) |
380 | return NULL; | 381 | return NULL; |
381 | else | 382 | else |
382 | return newtbl; | 383 | return newtbl; |
384 | |||
385 | errcopy: | ||
386 | for (i = 0; i <= newtbl->hash_mask; i++) { | ||
387 | hlist_for_each_safe(p, q, &newtbl->hash_buckets[i]) | ||
388 | tbl->free_node(p, 0); | ||
389 | } | ||
390 | kfree(newtbl->hash_buckets); | ||
391 | kfree(newtbl->hashwlock); | ||
392 | kfree(newtbl); | ||
393 | return NULL; | ||
383 | } | 394 | } |
384 | 395 | ||
385 | /** | 396 | /** |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 2e161f6d8288..669eafafe497 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -109,7 +109,7 @@ struct mesh_table { | |||
109 | __u32 hash_rnd; /* Used for hash generation */ | 109 | __u32 hash_rnd; /* Used for hash generation */ |
110 | atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */ | 110 | atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */ |
111 | void (*free_node) (struct hlist_node *p, bool free_leafs); | 111 | void (*free_node) (struct hlist_node *p, bool free_leafs); |
112 | void (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl); | 112 | int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl); |
113 | int size_order; | 113 | int size_order; |
114 | int mean_chain_len; | 114 | int mean_chain_len; |
115 | }; | 115 | }; |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 0b6c4bfe3e78..512bfa112c6a 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -463,7 +463,7 @@ static void mesh_path_node_free(struct hlist_node *p, bool free_leafs) | |||
463 | kfree(node); | 463 | kfree(node); |
464 | } | 464 | } |
465 | 465 | ||
466 | static void mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) | 466 | static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) |
467 | { | 467 | { |
468 | struct mesh_path *mpath; | 468 | struct mesh_path *mpath; |
469 | struct mpath_node *node, *new_node; | 469 | struct mpath_node *node, *new_node; |
@@ -476,6 +476,7 @@ static void mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) | |||
476 | hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl); | 476 | hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl); |
477 | hlist_add_head(&new_node->list, | 477 | hlist_add_head(&new_node->list, |
478 | &newtbl->hash_buckets[hash_idx]); | 478 | &newtbl->hash_buckets[hash_idx]); |
479 | return 0; | ||
479 | } | 480 | } |
480 | 481 | ||
481 | int mesh_pathtbl_init(void) | 482 | int mesh_pathtbl_init(void) |