diff options
author | Jan Engelhardt <jengelh@medozas.de> | 2010-02-24 12:35:37 -0500 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-02-24 12:35:37 -0500 |
commit | 6bdb331bc6910d1ccb74dc9852fc858c5916c927 (patch) | |
tree | d77dd2df2d6d43ce25703ce8c9ecab0173c14a7f /net/ipv6 | |
parent | dcea992aca82cb08b4674c4c783e325835408d1e (diff) |
netfilter: xtables: optimize call flow around xt_ematch_foreach
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 93 |
1 files changed, 31 insertions, 62 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1537e6bad5d9..c5a963e4b545 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -603,14 +603,10 @@ mark_source_chains(const struct xt_table_info *newinfo, | |||
603 | return 1; | 603 | return 1; |
604 | } | 604 | } |
605 | 605 | ||
606 | static int | 606 | static void cleanup_match(struct ip6t_entry_match *m, struct net *net) |
607 | cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i) | ||
608 | { | 607 | { |
609 | struct xt_mtdtor_param par; | 608 | struct xt_mtdtor_param par; |
610 | 609 | ||
611 | if (i && (*i)-- == 0) | ||
612 | return 1; | ||
613 | |||
614 | par.net = net; | 610 | par.net = net; |
615 | par.match = m->u.kernel.match; | 611 | par.match = m->u.kernel.match; |
616 | par.matchinfo = m->data; | 612 | par.matchinfo = m->data; |
@@ -618,7 +614,6 @@ cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i) | |||
618 | if (par.match->destroy != NULL) | 614 | if (par.match->destroy != NULL) |
619 | par.match->destroy(&par); | 615 | par.match->destroy(&par); |
620 | module_put(par.match->me); | 616 | module_put(par.match->me); |
621 | return 0; | ||
622 | } | 617 | } |
623 | 618 | ||
624 | static int | 619 | static int |
@@ -642,8 +637,7 @@ check_entry(const struct ip6t_entry *e, const char *name) | |||
642 | return 0; | 637 | return 0; |
643 | } | 638 | } |
644 | 639 | ||
645 | static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, | 640 | static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par) |
646 | unsigned int *i) | ||
647 | { | 641 | { |
648 | const struct ip6t_ip6 *ipv6 = par->entryinfo; | 642 | const struct ip6t_ip6 *ipv6 = par->entryinfo; |
649 | int ret; | 643 | int ret; |
@@ -658,13 +652,11 @@ static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, | |||
658 | par.match->name); | 652 | par.match->name); |
659 | return ret; | 653 | return ret; |
660 | } | 654 | } |
661 | ++*i; | ||
662 | return 0; | 655 | return 0; |
663 | } | 656 | } |
664 | 657 | ||
665 | static int | 658 | static int |
666 | find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, | 659 | find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par) |
667 | unsigned int *i) | ||
668 | { | 660 | { |
669 | struct xt_match *match; | 661 | struct xt_match *match; |
670 | int ret; | 662 | int ret; |
@@ -678,7 +670,7 @@ find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, | |||
678 | } | 670 | } |
679 | m->u.kernel.match = match; | 671 | m->u.kernel.match = match; |
680 | 672 | ||
681 | ret = check_match(m, par, i); | 673 | ret = check_match(m, par); |
682 | if (ret) | 674 | if (ret) |
683 | goto err; | 675 | goto err; |
684 | 676 | ||
@@ -735,12 +727,11 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, | |||
735 | mtpar.hook_mask = e->comefrom; | 727 | mtpar.hook_mask = e->comefrom; |
736 | mtpar.family = NFPROTO_IPV6; | 728 | mtpar.family = NFPROTO_IPV6; |
737 | xt_ematch_foreach(ematch, e) { | 729 | xt_ematch_foreach(ematch, e) { |
738 | ret = find_check_match(ematch, &mtpar, &j); | 730 | ret = find_check_match(ematch, &mtpar); |
739 | if (ret != 0) | 731 | if (ret != 0) |
740 | break; | 732 | goto cleanup_matches; |
733 | ++j; | ||
741 | } | 734 | } |
742 | if (ret != 0) | ||
743 | goto cleanup_matches; | ||
744 | 735 | ||
745 | t = ip6t_get_target(e); | 736 | t = ip6t_get_target(e); |
746 | target = try_then_request_module(xt_find_target(AF_INET6, | 737 | target = try_then_request_module(xt_find_target(AF_INET6, |
@@ -761,9 +752,11 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, | |||
761 | err: | 752 | err: |
762 | module_put(t->u.kernel.target->me); | 753 | module_put(t->u.kernel.target->me); |
763 | cleanup_matches: | 754 | cleanup_matches: |
764 | xt_ematch_foreach(ematch, e) | 755 | xt_ematch_foreach(ematch, e) { |
765 | if (cleanup_match(ematch, net, &j) != 0) | 756 | if (j-- == 0) |
766 | break; | 757 | break; |
758 | cleanup_match(ematch, net); | ||
759 | } | ||
767 | return ret; | 760 | return ret; |
768 | } | 761 | } |
769 | 762 | ||
@@ -837,8 +830,7 @@ static void cleanup_entry(struct ip6t_entry *e, struct net *net) | |||
837 | 830 | ||
838 | /* Cleanup all matches */ | 831 | /* Cleanup all matches */ |
839 | xt_ematch_foreach(ematch, e) | 832 | xt_ematch_foreach(ematch, e) |
840 | if (cleanup_match(ematch, net, NULL) != 0) | 833 | cleanup_match(ematch, net); |
841 | break; | ||
842 | t = ip6t_get_target(e); | 834 | t = ip6t_get_target(e); |
843 | 835 | ||
844 | par.net = net; | 836 | par.net = net; |
@@ -1094,13 +1086,6 @@ static int compat_standard_to_user(void __user *dst, const void *src) | |||
1094 | return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; | 1086 | return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; |
1095 | } | 1087 | } |
1096 | 1088 | ||
1097 | static inline int | ||
1098 | compat_calc_match(const struct ip6t_entry_match *m, int *size) | ||
1099 | { | ||
1100 | *size += xt_compat_match_offset(m->u.kernel.match); | ||
1101 | return 0; | ||
1102 | } | ||
1103 | |||
1104 | static int compat_calc_entry(const struct ip6t_entry *e, | 1089 | static int compat_calc_entry(const struct ip6t_entry *e, |
1105 | const struct xt_table_info *info, | 1090 | const struct xt_table_info *info, |
1106 | const void *base, struct xt_table_info *newinfo) | 1091 | const void *base, struct xt_table_info *newinfo) |
@@ -1113,8 +1098,7 @@ static int compat_calc_entry(const struct ip6t_entry *e, | |||
1113 | off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); | 1098 | off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); |
1114 | entry_offset = (void *)e - base; | 1099 | entry_offset = (void *)e - base; |
1115 | xt_ematch_foreach(ematch, e) | 1100 | xt_ematch_foreach(ematch, e) |
1116 | if (compat_calc_match(ematch, &off) != 0) | 1101 | off += xt_compat_match_offset(ematch->u.kernel.match); |
1117 | break; | ||
1118 | t = ip6t_get_target_c(e); | 1102 | t = ip6t_get_target_c(e); |
1119 | off += xt_compat_target_offset(t->u.kernel.target); | 1103 | off += xt_compat_target_offset(t->u.kernel.target); |
1120 | newinfo->size -= off; | 1104 | newinfo->size -= off; |
@@ -1508,11 +1492,9 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, | |||
1508 | xt_ematch_foreach(ematch, e) { | 1492 | xt_ematch_foreach(ematch, e) { |
1509 | ret = xt_compat_match_to_user(ematch, dstptr, size); | 1493 | ret = xt_compat_match_to_user(ematch, dstptr, size); |
1510 | if (ret != 0) | 1494 | if (ret != 0) |
1511 | break; | 1495 | return ret; |
1512 | } | 1496 | } |
1513 | target_offset = e->target_offset - (origsize - *size); | 1497 | target_offset = e->target_offset - (origsize - *size); |
1514 | if (ret) | ||
1515 | return ret; | ||
1516 | t = ip6t_get_target(e); | 1498 | t = ip6t_get_target(e); |
1517 | ret = xt_compat_target_to_user(t, dstptr, size); | 1499 | ret = xt_compat_target_to_user(t, dstptr, size); |
1518 | if (ret) | 1500 | if (ret) |
@@ -1529,7 +1511,7 @@ compat_find_calc_match(struct ip6t_entry_match *m, | |||
1529 | const char *name, | 1511 | const char *name, |
1530 | const struct ip6t_ip6 *ipv6, | 1512 | const struct ip6t_ip6 *ipv6, |
1531 | unsigned int hookmask, | 1513 | unsigned int hookmask, |
1532 | int *size, unsigned int *i) | 1514 | int *size) |
1533 | { | 1515 | { |
1534 | struct xt_match *match; | 1516 | struct xt_match *match; |
1535 | 1517 | ||
@@ -1543,18 +1525,6 @@ compat_find_calc_match(struct ip6t_entry_match *m, | |||
1543 | } | 1525 | } |
1544 | m->u.kernel.match = match; | 1526 | m->u.kernel.match = match; |
1545 | *size += xt_compat_match_offset(match); | 1527 | *size += xt_compat_match_offset(match); |
1546 | |||
1547 | (*i)++; | ||
1548 | return 0; | ||
1549 | } | ||
1550 | |||
1551 | static int | ||
1552 | compat_release_match(struct ip6t_entry_match *m, unsigned int *i) | ||
1553 | { | ||
1554 | if (i && (*i)-- == 0) | ||
1555 | return 1; | ||
1556 | |||
1557 | module_put(m->u.kernel.match->me); | ||
1558 | return 0; | 1528 | return 0; |
1559 | } | 1529 | } |
1560 | 1530 | ||
@@ -1565,8 +1535,7 @@ static void compat_release_entry(struct compat_ip6t_entry *e) | |||
1565 | 1535 | ||
1566 | /* Cleanup all matches */ | 1536 | /* Cleanup all matches */ |
1567 | xt_ematch_foreach(ematch, e) | 1537 | xt_ematch_foreach(ematch, e) |
1568 | if (compat_release_match(ematch, NULL) != 0) | 1538 | module_put(ematch->u.kernel.match->me); |
1569 | break; | ||
1570 | t = compat_ip6t_get_target(e); | 1539 | t = compat_ip6t_get_target(e); |
1571 | module_put(t->u.kernel.target->me); | 1540 | module_put(t->u.kernel.target->me); |
1572 | } | 1541 | } |
@@ -1612,12 +1581,11 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, | |||
1612 | j = 0; | 1581 | j = 0; |
1613 | xt_ematch_foreach(ematch, e) { | 1582 | xt_ematch_foreach(ematch, e) { |
1614 | ret = compat_find_calc_match(ematch, name, | 1583 | ret = compat_find_calc_match(ematch, name, |
1615 | &e->ipv6, e->comefrom, &off, &j); | 1584 | &e->ipv6, e->comefrom, &off); |
1616 | if (ret != 0) | 1585 | if (ret != 0) |
1617 | break; | 1586 | goto release_matches; |
1587 | ++j; | ||
1618 | } | 1588 | } |
1619 | if (ret != 0) | ||
1620 | goto release_matches; | ||
1621 | 1589 | ||
1622 | t = compat_ip6t_get_target(e); | 1590 | t = compat_ip6t_get_target(e); |
1623 | target = try_then_request_module(xt_find_target(AF_INET6, | 1591 | target = try_then_request_module(xt_find_target(AF_INET6, |
@@ -1654,9 +1622,11 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, | |||
1654 | out: | 1622 | out: |
1655 | module_put(t->u.kernel.target->me); | 1623 | module_put(t->u.kernel.target->me); |
1656 | release_matches: | 1624 | release_matches: |
1657 | xt_ematch_foreach(ematch, e) | 1625 | xt_ematch_foreach(ematch, e) { |
1658 | if (compat_release_match(ematch, &j) != 0) | 1626 | if (j-- == 0) |
1659 | break; | 1627 | break; |
1628 | module_put(ematch->u.kernel.match->me); | ||
1629 | } | ||
1660 | return ret; | 1630 | return ret; |
1661 | } | 1631 | } |
1662 | 1632 | ||
@@ -1684,10 +1654,8 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, | |||
1684 | xt_ematch_foreach(ematch, e) { | 1654 | xt_ematch_foreach(ematch, e) { |
1685 | ret = xt_compat_match_from_user(ematch, dstptr, size); | 1655 | ret = xt_compat_match_from_user(ematch, dstptr, size); |
1686 | if (ret != 0) | 1656 | if (ret != 0) |
1687 | break; | 1657 | return ret; |
1688 | } | 1658 | } |
1689 | if (ret) | ||
1690 | return ret; | ||
1691 | de->target_offset = e->target_offset - (origsize - *size); | 1659 | de->target_offset = e->target_offset - (origsize - *size); |
1692 | t = compat_ip6t_get_target(e); | 1660 | t = compat_ip6t_get_target(e); |
1693 | target = t->u.kernel.target; | 1661 | target = t->u.kernel.target; |
@@ -1718,12 +1686,11 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, | |||
1718 | mtpar.hook_mask = e->comefrom; | 1686 | mtpar.hook_mask = e->comefrom; |
1719 | mtpar.family = NFPROTO_IPV6; | 1687 | mtpar.family = NFPROTO_IPV6; |
1720 | xt_ematch_foreach(ematch, e) { | 1688 | xt_ematch_foreach(ematch, e) { |
1721 | ret = check_match(ematch, &mtpar, &j); | 1689 | ret = check_match(ematch, &mtpar); |
1722 | if (ret != 0) | 1690 | if (ret != 0) |
1723 | break; | 1691 | goto cleanup_matches; |
1692 | ++j; | ||
1724 | } | 1693 | } |
1725 | if (ret) | ||
1726 | goto cleanup_matches; | ||
1727 | 1694 | ||
1728 | ret = check_target(e, net, name); | 1695 | ret = check_target(e, net, name); |
1729 | if (ret) | 1696 | if (ret) |
@@ -1731,9 +1698,11 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, | |||
1731 | return 0; | 1698 | return 0; |
1732 | 1699 | ||
1733 | cleanup_matches: | 1700 | cleanup_matches: |
1734 | xt_ematch_foreach(ematch, e) | 1701 | xt_ematch_foreach(ematch, e) { |
1735 | if (cleanup_match(ematch, net, &j) != 0) | 1702 | if (j-- == 0) |
1736 | break; | 1703 | break; |
1704 | cleanup_match(ematch, net); | ||
1705 | } | ||
1737 | return ret; | 1706 | return ret; |
1738 | } | 1707 | } |
1739 | 1708 | ||