diff options
Diffstat (limited to 'net/sched/cls_u32.c')
-rw-r--r-- | net/sched/cls_u32.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 6c7601a530e3..ed8b6a24b9e9 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -96,7 +96,7 @@ struct tc_u_hnode { | |||
96 | 96 | ||
97 | struct tc_u_common { | 97 | struct tc_u_common { |
98 | struct tc_u_hnode __rcu *hlist; | 98 | struct tc_u_hnode __rcu *hlist; |
99 | struct tcf_block *block; | 99 | void *ptr; |
100 | int refcnt; | 100 | int refcnt; |
101 | struct idr handle_idr; | 101 | struct idr handle_idr; |
102 | struct hlist_node hnode; | 102 | struct hlist_node hnode; |
@@ -330,9 +330,25 @@ static struct hlist_head *tc_u_common_hash; | |||
330 | #define U32_HASH_SHIFT 10 | 330 | #define U32_HASH_SHIFT 10 |
331 | #define U32_HASH_SIZE (1 << U32_HASH_SHIFT) | 331 | #define U32_HASH_SIZE (1 << U32_HASH_SHIFT) |
332 | 332 | ||
333 | static void *tc_u_common_ptr(const struct tcf_proto *tp) | ||
334 | { | ||
335 | struct tcf_block *block = tp->chain->block; | ||
336 | |||
337 | /* The block sharing is currently supported only | ||
338 | * for classless qdiscs. In that case we use block | ||
339 | * for tc_u_common identification. In case the | ||
340 | * block is not shared, block->q is a valid pointer | ||
341 | * and we can use that. That works for classful qdiscs. | ||
342 | */ | ||
343 | if (tcf_block_shared(block)) | ||
344 | return block; | ||
345 | else | ||
346 | return block->q; | ||
347 | } | ||
348 | |||
333 | static unsigned int tc_u_hash(const struct tcf_proto *tp) | 349 | static unsigned int tc_u_hash(const struct tcf_proto *tp) |
334 | { | 350 | { |
335 | return hash_ptr(tp->chain->block, U32_HASH_SHIFT); | 351 | return hash_ptr(tc_u_common_ptr(tp), U32_HASH_SHIFT); |
336 | } | 352 | } |
337 | 353 | ||
338 | static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp) | 354 | static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp) |
@@ -342,7 +358,7 @@ static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp) | |||
342 | 358 | ||
343 | h = tc_u_hash(tp); | 359 | h = tc_u_hash(tp); |
344 | hlist_for_each_entry(tc, &tc_u_common_hash[h], hnode) { | 360 | hlist_for_each_entry(tc, &tc_u_common_hash[h], hnode) { |
345 | if (tc->block == tp->chain->block) | 361 | if (tc->ptr == tc_u_common_ptr(tp)) |
346 | return tc; | 362 | return tc; |
347 | } | 363 | } |
348 | return NULL; | 364 | return NULL; |
@@ -371,7 +387,7 @@ static int u32_init(struct tcf_proto *tp) | |||
371 | kfree(root_ht); | 387 | kfree(root_ht); |
372 | return -ENOBUFS; | 388 | return -ENOBUFS; |
373 | } | 389 | } |
374 | tp_c->block = tp->chain->block; | 390 | tp_c->ptr = tc_u_common_ptr(tp); |
375 | INIT_HLIST_NODE(&tp_c->hnode); | 391 | INIT_HLIST_NODE(&tp_c->hnode); |
376 | idr_init(&tp_c->handle_idr); | 392 | idr_init(&tp_c->handle_idr); |
377 | 393 | ||