aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-10-14 16:53:34 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-17 16:53:15 -0400
commit117a8cdea3647e8e11fac10d14eafefc20f9bda5 (patch)
treeb030a78c033998bdc725935b4123695bfb8c24e9 /net/ipv4
parent9bef83edfba72ba58b42c14fb046da2199574bc0 (diff)
fib_hash: RCU conversion phase 1
First step for RCU conversion of fib_hash : struct fn_zone are created and never deleted. Very classic conversion, using rcu_assign_pointer(), rcu_dereference() and rtnl_dereference() verbs. __rcu markers on fz_next and fn_zone_list They are created under RTNL, we dont need fib_hash_lock anymore in fn_new_zone(). Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/fib_hash.c57
1 files changed, 38 insertions, 19 deletions
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 10001aa40692..04f05a96b75b 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -57,7 +57,7 @@ struct fib_node {
57#define EMBEDDED_HASH_SIZE (L1_CACHE_BYTES / sizeof(struct hlist_head)) 57#define EMBEDDED_HASH_SIZE (L1_CACHE_BYTES / sizeof(struct hlist_head))
58 58
59struct fn_zone { 59struct fn_zone {
60 struct fn_zone *fz_next; /* Next not empty zone */ 60 struct fn_zone __rcu *fz_next; /* Next not empty zone */
61 struct hlist_head *fz_hash; /* Hash table pointer */ 61 struct hlist_head *fz_hash; /* Hash table pointer */
62 u32 fz_hashmask; /* (fz_divisor - 1) */ 62 u32 fz_hashmask; /* (fz_divisor - 1) */
63 63
@@ -73,8 +73,8 @@ struct fn_zone {
73}; 73};
74 74
75struct fn_hash { 75struct fn_hash {
76 struct fn_zone *fn_zones[33]; 76 struct fn_zone *fn_zones[33];
77 struct fn_zone *fn_zone_list; 77 struct fn_zone __rcu *fn_zone_list;
78}; 78};
79 79
80static inline u32 fn_hash(__be32 key, struct fn_zone *fz) 80static inline u32 fn_hash(__be32 key, struct fn_zone *fz)
@@ -219,21 +219,21 @@ fn_new_zone(struct fn_hash *table, int z)
219 fz->fz_mask = inet_make_mask(z); 219 fz->fz_mask = inet_make_mask(z);
220 220
221 /* Find the first not empty zone with more specific mask */ 221 /* Find the first not empty zone with more specific mask */
222 for (i=z+1; i<=32; i++) 222 for (i = z + 1; i <= 32; i++)
223 if (table->fn_zones[i]) 223 if (table->fn_zones[i])
224 break; 224 break;
225 write_lock_bh(&fib_hash_lock); 225 if (i > 32) {
226 if (i>32) {
227 /* No more specific masks, we are the first. */ 226 /* No more specific masks, we are the first. */
228 fz->fz_next = table->fn_zone_list; 227 rcu_assign_pointer(fz->fz_next,
229 table->fn_zone_list = fz; 228 rtnl_dereference(table->fn_zone_list));
229 rcu_assign_pointer(table->fn_zone_list, fz);
230 } else { 230 } else {
231 fz->fz_next = table->fn_zones[i]->fz_next; 231 rcu_assign_pointer(fz->fz_next,
232 table->fn_zones[i]->fz_next = fz; 232 rtnl_dereference(table->fn_zones[i]->fz_next));
233 rcu_assign_pointer(table->fn_zones[i]->fz_next, fz);
233 } 234 }
234 table->fn_zones[z] = fz; 235 table->fn_zones[z] = fz;
235 fib_hash_genid++; 236 fib_hash_genid++;
236 write_unlock_bh(&fib_hash_lock);
237 return fz; 237 return fz;
238} 238}
239 239
@@ -245,8 +245,11 @@ int fib_table_lookup(struct fib_table *tb,
245 struct fn_zone *fz; 245 struct fn_zone *fz;
246 struct fn_hash *t = (struct fn_hash *)tb->tb_data; 246 struct fn_hash *t = (struct fn_hash *)tb->tb_data;
247 247
248 rcu_read_lock();
248 read_lock(&fib_hash_lock); 249 read_lock(&fib_hash_lock);
249 for (fz = t->fn_zone_list; fz; fz = fz->fz_next) { 250 for (fz = rcu_dereference(t->fn_zone_list);
251 fz != NULL;
252 fz = rcu_dereference(fz->fz_next)) {
250 struct hlist_head *head; 253 struct hlist_head *head;
251 struct hlist_node *node; 254 struct hlist_node *node;
252 struct fib_node *f; 255 struct fib_node *f;
@@ -267,6 +270,7 @@ int fib_table_lookup(struct fib_table *tb,
267 err = 1; 270 err = 1;
268out: 271out:
269 read_unlock(&fib_hash_lock); 272 read_unlock(&fib_hash_lock);
273 rcu_read_unlock();
270 return err; 274 return err;
271} 275}
272 276
@@ -362,6 +366,7 @@ static struct fib_node *fib_find_node(struct fn_zone *fz, __be32 key)
362 return NULL; 366 return NULL;
363} 367}
364 368
369/* Caller must hold RTNL. */
365int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) 370int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
366{ 371{
367 struct fn_hash *table = (struct fn_hash *) tb->tb_data; 372 struct fn_hash *table = (struct fn_hash *) tb->tb_data;
@@ -657,13 +662,16 @@ static int fn_flush_list(struct fn_zone *fz, int idx)
657 return found; 662 return found;
658} 663}
659 664
665/* caller must hold RTNL. */
660int fib_table_flush(struct fib_table *tb) 666int fib_table_flush(struct fib_table *tb)
661{ 667{
662 struct fn_hash *table = (struct fn_hash *) tb->tb_data; 668 struct fn_hash *table = (struct fn_hash *) tb->tb_data;
663 struct fn_zone *fz; 669 struct fn_zone *fz;
664 int found = 0; 670 int found = 0;
665 671
666 for (fz = table->fn_zone_list; fz; fz = fz->fz_next) { 672 for (fz = rtnl_dereference(table->fn_zone_list);
673 fz != NULL;
674 fz = rtnl_dereference(fz->fz_next)) {
667 int i; 675 int i;
668 676
669 for (i = fz->fz_divisor - 1; i >= 0; i--) 677 for (i = fz->fz_divisor - 1; i >= 0; i--)
@@ -741,23 +749,29 @@ fn_hash_dump_zone(struct sk_buff *skb, struct netlink_callback *cb,
741int fib_table_dump(struct fib_table *tb, struct sk_buff *skb, 749int fib_table_dump(struct fib_table *tb, struct sk_buff *skb,
742 struct netlink_callback *cb) 750 struct netlink_callback *cb)
743{ 751{
744 int m, s_m; 752 int m = 0, s_m;
745 struct fn_zone *fz; 753 struct fn_zone *fz;
746 struct fn_hash *table = (struct fn_hash *)tb->tb_data; 754 struct fn_hash *table = (struct fn_hash *)tb->tb_data;
747 755
748 s_m = cb->args[2]; 756 s_m = cb->args[2];
757 rcu_read_lock();
749 read_lock(&fib_hash_lock); 758 read_lock(&fib_hash_lock);
750 for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) { 759 for (fz = rcu_dereference(table->fn_zone_list);
751 if (m < s_m) continue; 760 fz != NULL;
761 fz = rcu_dereference(fz->fz_next), m++) {
762 if (m < s_m)
763 continue;
752 if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) { 764 if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) {
753 cb->args[2] = m; 765 cb->args[2] = m;
754 read_unlock(&fib_hash_lock); 766 read_unlock(&fib_hash_lock);
767 rcu_read_unlock();
755 return -1; 768 return -1;
756 } 769 }
757 memset(&cb->args[3], 0, 770 memset(&cb->args[3], 0,
758 sizeof(cb->args) - 3*sizeof(cb->args[0])); 771 sizeof(cb->args) - 3*sizeof(cb->args[0]));
759 } 772 }
760 read_unlock(&fib_hash_lock); 773 read_unlock(&fib_hash_lock);
774 rcu_read_unlock();
761 cb->args[2] = m; 775 cb->args[2] = m;
762 return skb->len; 776 return skb->len;
763} 777}
@@ -820,8 +834,9 @@ static struct fib_alias *fib_get_first(struct seq_file *seq)
820 iter->genid = fib_hash_genid; 834 iter->genid = fib_hash_genid;
821 iter->valid = 1; 835 iter->valid = 1;
822 836
823 for (iter->zone = table->fn_zone_list; iter->zone; 837 for (iter->zone = rcu_dereference(table->fn_zone_list);
824 iter->zone = iter->zone->fz_next) { 838 iter->zone != NULL;
839 iter->zone = rcu_dereference(iter->zone->fz_next)) {
825 int maxslot; 840 int maxslot;
826 841
827 if (!iter->zone->fz_nent) 842 if (!iter->zone->fz_nent)
@@ -906,7 +921,7 @@ static struct fib_alias *fib_get_next(struct seq_file *seq)
906 } 921 }
907 } 922 }
908 923
909 iter->zone = iter->zone->fz_next; 924 iter->zone = rcu_dereference(iter->zone->fz_next);
910 925
911 if (!iter->zone) 926 if (!iter->zone)
912 goto out; 927 goto out;
@@ -946,9 +961,11 @@ static struct fib_alias *fib_get_idx(struct seq_file *seq, loff_t pos)
946 961
947static void *fib_seq_start(struct seq_file *seq, loff_t *pos) 962static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
948 __acquires(fib_hash_lock) 963 __acquires(fib_hash_lock)
964 __acquires(RCU)
949{ 965{
950 void *v = NULL; 966 void *v = NULL;
951 967
968 rcu_read_lock();
952 read_lock(&fib_hash_lock); 969 read_lock(&fib_hash_lock);
953 if (fib_get_table(seq_file_net(seq), RT_TABLE_MAIN)) 970 if (fib_get_table(seq_file_net(seq), RT_TABLE_MAIN))
954 v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; 971 v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
@@ -963,8 +980,10 @@ static void *fib_seq_next(struct seq_file *seq, void *v, loff_t *pos)
963 980
964static void fib_seq_stop(struct seq_file *seq, void *v) 981static void fib_seq_stop(struct seq_file *seq, void *v)
965 __releases(fib_hash_lock) 982 __releases(fib_hash_lock)
983 __releases(RCU)
966{ 984{
967 read_unlock(&fib_hash_lock); 985 read_unlock(&fib_hash_lock);
986 rcu_read_unlock();
968} 987}
969 988
970static unsigned fib_flag_trans(int type, __be32 mask, struct fib_info *fi) 989static unsigned fib_flag_trans(int type, __be32 mask, struct fib_info *fi)