diff options
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_state.c | 58 |
1 files changed, 30 insertions, 28 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 64780a6f7b86..1522f19f273a 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -1644,27 +1644,26 @@ static void xfrm_replay_timer_handler(unsigned long data) | |||
1644 | } | 1644 | } |
1645 | 1645 | ||
1646 | static LIST_HEAD(xfrm_km_list); | 1646 | static LIST_HEAD(xfrm_km_list); |
1647 | static DEFINE_RWLOCK(xfrm_km_lock); | ||
1648 | 1647 | ||
1649 | void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) | 1648 | void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) |
1650 | { | 1649 | { |
1651 | struct xfrm_mgr *km; | 1650 | struct xfrm_mgr *km; |
1652 | 1651 | ||
1653 | read_lock(&xfrm_km_lock); | 1652 | rcu_read_lock(); |
1654 | list_for_each_entry(km, &xfrm_km_list, list) | 1653 | list_for_each_entry_rcu(km, &xfrm_km_list, list) |
1655 | if (km->notify_policy) | 1654 | if (km->notify_policy) |
1656 | km->notify_policy(xp, dir, c); | 1655 | km->notify_policy(xp, dir, c); |
1657 | read_unlock(&xfrm_km_lock); | 1656 | rcu_read_unlock(); |
1658 | } | 1657 | } |
1659 | 1658 | ||
1660 | void km_state_notify(struct xfrm_state *x, const struct km_event *c) | 1659 | void km_state_notify(struct xfrm_state *x, const struct km_event *c) |
1661 | { | 1660 | { |
1662 | struct xfrm_mgr *km; | 1661 | struct xfrm_mgr *km; |
1663 | read_lock(&xfrm_km_lock); | 1662 | rcu_read_lock(); |
1664 | list_for_each_entry(km, &xfrm_km_list, list) | 1663 | list_for_each_entry_rcu(km, &xfrm_km_list, list) |
1665 | if (km->notify) | 1664 | if (km->notify) |
1666 | km->notify(x, c); | 1665 | km->notify(x, c); |
1667 | read_unlock(&xfrm_km_lock); | 1666 | rcu_read_unlock(); |
1668 | } | 1667 | } |
1669 | 1668 | ||
1670 | EXPORT_SYMBOL(km_policy_notify); | 1669 | EXPORT_SYMBOL(km_policy_notify); |
@@ -1694,13 +1693,13 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) | |||
1694 | int err = -EINVAL, acqret; | 1693 | int err = -EINVAL, acqret; |
1695 | struct xfrm_mgr *km; | 1694 | struct xfrm_mgr *km; |
1696 | 1695 | ||
1697 | read_lock(&xfrm_km_lock); | 1696 | rcu_read_lock(); |
1698 | list_for_each_entry(km, &xfrm_km_list, list) { | 1697 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { |
1699 | acqret = km->acquire(x, t, pol); | 1698 | acqret = km->acquire(x, t, pol); |
1700 | if (!acqret) | 1699 | if (!acqret) |
1701 | err = acqret; | 1700 | err = acqret; |
1702 | } | 1701 | } |
1703 | read_unlock(&xfrm_km_lock); | 1702 | rcu_read_unlock(); |
1704 | return err; | 1703 | return err; |
1705 | } | 1704 | } |
1706 | EXPORT_SYMBOL(km_query); | 1705 | EXPORT_SYMBOL(km_query); |
@@ -1710,14 +1709,14 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport) | |||
1710 | int err = -EINVAL; | 1709 | int err = -EINVAL; |
1711 | struct xfrm_mgr *km; | 1710 | struct xfrm_mgr *km; |
1712 | 1711 | ||
1713 | read_lock(&xfrm_km_lock); | 1712 | rcu_read_lock(); |
1714 | list_for_each_entry(km, &xfrm_km_list, list) { | 1713 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { |
1715 | if (km->new_mapping) | 1714 | if (km->new_mapping) |
1716 | err = km->new_mapping(x, ipaddr, sport); | 1715 | err = km->new_mapping(x, ipaddr, sport); |
1717 | if (!err) | 1716 | if (!err) |
1718 | break; | 1717 | break; |
1719 | } | 1718 | } |
1720 | read_unlock(&xfrm_km_lock); | 1719 | rcu_read_unlock(); |
1721 | return err; | 1720 | return err; |
1722 | } | 1721 | } |
1723 | EXPORT_SYMBOL(km_new_mapping); | 1722 | EXPORT_SYMBOL(km_new_mapping); |
@@ -1746,15 +1745,15 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | |||
1746 | int ret; | 1745 | int ret; |
1747 | struct xfrm_mgr *km; | 1746 | struct xfrm_mgr *km; |
1748 | 1747 | ||
1749 | read_lock(&xfrm_km_lock); | 1748 | rcu_read_lock(); |
1750 | list_for_each_entry(km, &xfrm_km_list, list) { | 1749 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { |
1751 | if (km->migrate) { | 1750 | if (km->migrate) { |
1752 | ret = km->migrate(sel, dir, type, m, num_migrate, k); | 1751 | ret = km->migrate(sel, dir, type, m, num_migrate, k); |
1753 | if (!ret) | 1752 | if (!ret) |
1754 | err = ret; | 1753 | err = ret; |
1755 | } | 1754 | } |
1756 | } | 1755 | } |
1757 | read_unlock(&xfrm_km_lock); | 1756 | rcu_read_unlock(); |
1758 | return err; | 1757 | return err; |
1759 | } | 1758 | } |
1760 | EXPORT_SYMBOL(km_migrate); | 1759 | EXPORT_SYMBOL(km_migrate); |
@@ -1766,15 +1765,15 @@ int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address | |||
1766 | int ret; | 1765 | int ret; |
1767 | struct xfrm_mgr *km; | 1766 | struct xfrm_mgr *km; |
1768 | 1767 | ||
1769 | read_lock(&xfrm_km_lock); | 1768 | rcu_read_lock(); |
1770 | list_for_each_entry(km, &xfrm_km_list, list) { | 1769 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { |
1771 | if (km->report) { | 1770 | if (km->report) { |
1772 | ret = km->report(net, proto, sel, addr); | 1771 | ret = km->report(net, proto, sel, addr); |
1773 | if (!ret) | 1772 | if (!ret) |
1774 | err = ret; | 1773 | err = ret; |
1775 | } | 1774 | } |
1776 | } | 1775 | } |
1777 | read_unlock(&xfrm_km_lock); | 1776 | rcu_read_unlock(); |
1778 | return err; | 1777 | return err; |
1779 | } | 1778 | } |
1780 | EXPORT_SYMBOL(km_report); | 1779 | EXPORT_SYMBOL(km_report); |
@@ -1798,14 +1797,14 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen | |||
1798 | goto out; | 1797 | goto out; |
1799 | 1798 | ||
1800 | err = -EINVAL; | 1799 | err = -EINVAL; |
1801 | read_lock(&xfrm_km_lock); | 1800 | rcu_read_lock(); |
1802 | list_for_each_entry(km, &xfrm_km_list, list) { | 1801 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { |
1803 | pol = km->compile_policy(sk, optname, data, | 1802 | pol = km->compile_policy(sk, optname, data, |
1804 | optlen, &err); | 1803 | optlen, &err); |
1805 | if (err >= 0) | 1804 | if (err >= 0) |
1806 | break; | 1805 | break; |
1807 | } | 1806 | } |
1808 | read_unlock(&xfrm_km_lock); | 1807 | rcu_read_unlock(); |
1809 | 1808 | ||
1810 | if (err >= 0) { | 1809 | if (err >= 0) { |
1811 | xfrm_sk_policy_insert(sk, err, pol); | 1810 | xfrm_sk_policy_insert(sk, err, pol); |
@@ -1819,20 +1818,23 @@ out: | |||
1819 | } | 1818 | } |
1820 | EXPORT_SYMBOL(xfrm_user_policy); | 1819 | EXPORT_SYMBOL(xfrm_user_policy); |
1821 | 1820 | ||
1821 | static DEFINE_SPINLOCK(xfrm_km_lock); | ||
1822 | |||
1822 | int xfrm_register_km(struct xfrm_mgr *km) | 1823 | int xfrm_register_km(struct xfrm_mgr *km) |
1823 | { | 1824 | { |
1824 | write_lock_bh(&xfrm_km_lock); | 1825 | spin_lock_bh(&xfrm_km_lock); |
1825 | list_add_tail(&km->list, &xfrm_km_list); | 1826 | list_add_tail_rcu(&km->list, &xfrm_km_list); |
1826 | write_unlock_bh(&xfrm_km_lock); | 1827 | spin_unlock_bh(&xfrm_km_lock); |
1827 | return 0; | 1828 | return 0; |
1828 | } | 1829 | } |
1829 | EXPORT_SYMBOL(xfrm_register_km); | 1830 | EXPORT_SYMBOL(xfrm_register_km); |
1830 | 1831 | ||
1831 | int xfrm_unregister_km(struct xfrm_mgr *km) | 1832 | int xfrm_unregister_km(struct xfrm_mgr *km) |
1832 | { | 1833 | { |
1833 | write_lock_bh(&xfrm_km_lock); | 1834 | spin_lock_bh(&xfrm_km_lock); |
1834 | list_del(&km->list); | 1835 | list_del_rcu(&km->list); |
1835 | write_unlock_bh(&xfrm_km_lock); | 1836 | spin_unlock_bh(&xfrm_km_lock); |
1837 | synchronize_rcu(); | ||
1836 | return 0; | 1838 | return 0; |
1837 | } | 1839 | } |
1838 | EXPORT_SYMBOL(xfrm_unregister_km); | 1840 | EXPORT_SYMBOL(xfrm_unregister_km); |