aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-01-23 14:00:16 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-23 14:00:16 -0500
commit93b9c1ddd3fb4a5b67d512e534b30070f9ecec28 (patch)
treef9584c9b3ff6873b2be043ea08c0fbb354c040df /net
parent4c133c39ae1bc541b3db5903a680da738a0c57e3 (diff)
parent02bfd8ecf5cf980ede53e30a903b102924fc32f4 (diff)
Merge branch 'testing' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next
Steffen Klassert says: ==================== 1) Add a statistic counter for invalid output states and remove a superfluous state valid check, from Li RongQing. 2) Probe for asynchronous block ciphers instead of synchronous block ciphers to make the asynchronous variants available even if no synchronous block ciphers are found, from Jussi Kivilinna. 3) Make rfc3686 asynchronous block cipher and make use of the new asynchronous variant, from Jussi Kivilinna. 4) Replace some rwlocks by rcu, from Cong Wang. 5) Remove some unused defines. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/xfrm/xfrm_algo.c3
-rw-r--r--net/xfrm/xfrm_output.c6
-rw-r--r--net/xfrm/xfrm_proc.c1
-rw-r--r--net/xfrm/xfrm_state.c131
4 files changed, 69 insertions, 72 deletions
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 4ce2d93162c1..f9a549554740 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -700,8 +700,7 @@ void xfrm_probe_algs(void)
700 } 700 }
701 701
702 for (i = 0; i < ealg_entries(); i++) { 702 for (i = 0; i < ealg_entries(); i++) {
703 status = crypto_has_blkcipher(ealg_list[i].name, 0, 703 status = crypto_has_ablkcipher(ealg_list[i].name, 0, 0);
704 CRYPTO_ALG_ASYNC);
705 if (ealg_list[i].available != status) 704 if (ealg_list[i].available != status)
706 ealg_list[i].available = status; 705 ealg_list[i].available = status;
707 } 706 }
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 95a338c89f99..3670526e70b9 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -61,6 +61,12 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
61 } 61 }
62 62
63 spin_lock_bh(&x->lock); 63 spin_lock_bh(&x->lock);
64
65 if (unlikely(x->km.state != XFRM_STATE_VALID)) {
66 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEINVALID);
67 goto error_nolock;
68 }
69
64 err = xfrm_state_check_expire(x); 70 err = xfrm_state_check_expire(x);
65 if (err) { 71 if (err) {
66 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEEXPIRED); 72 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEEXPIRED);
diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c
index d0a1af8ed584..603903853e89 100644
--- a/net/xfrm/xfrm_proc.c
+++ b/net/xfrm/xfrm_proc.c
@@ -43,6 +43,7 @@ static const struct snmp_mib xfrm_mib_list[] = {
43 SNMP_MIB_ITEM("XfrmOutPolDead", LINUX_MIB_XFRMOUTPOLDEAD), 43 SNMP_MIB_ITEM("XfrmOutPolDead", LINUX_MIB_XFRMOUTPOLDEAD),
44 SNMP_MIB_ITEM("XfrmOutPolError", LINUX_MIB_XFRMOUTPOLERROR), 44 SNMP_MIB_ITEM("XfrmOutPolError", LINUX_MIB_XFRMOUTPOLERROR),
45 SNMP_MIB_ITEM("XfrmFwdHdrError", LINUX_MIB_XFRMFWDHDRERROR), 45 SNMP_MIB_ITEM("XfrmFwdHdrError", LINUX_MIB_XFRMFWDHDRERROR),
46 SNMP_MIB_ITEM("XfrmOutStateInvalid", LINUX_MIB_XFRMOUTSTATEINVALID),
46 SNMP_MIB_SENTINEL 47 SNMP_MIB_SENTINEL
47}; 48};
48 49
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 3459692092ec..0adae918a7a2 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -158,8 +158,8 @@ out_unlock:
158 mutex_unlock(&hash_resize_mutex); 158 mutex_unlock(&hash_resize_mutex);
159} 159}
160 160
161static DEFINE_RWLOCK(xfrm_state_afinfo_lock); 161static DEFINE_SPINLOCK(xfrm_state_afinfo_lock);
162static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; 162static struct xfrm_state_afinfo __rcu *xfrm_state_afinfo[NPROTO];
163 163
164static DEFINE_SPINLOCK(xfrm_state_gc_lock); 164static DEFINE_SPINLOCK(xfrm_state_gc_lock);
165 165
@@ -168,58 +168,45 @@ int __xfrm_state_delete(struct xfrm_state *x);
168int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); 168int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
169void km_state_expired(struct xfrm_state *x, int hard, u32 portid); 169void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
170 170
171static struct xfrm_state_afinfo *xfrm_state_lock_afinfo(unsigned int family) 171static DEFINE_SPINLOCK(xfrm_type_lock);
172{
173 struct xfrm_state_afinfo *afinfo;
174 if (unlikely(family >= NPROTO))
175 return NULL;
176 write_lock_bh(&xfrm_state_afinfo_lock);
177 afinfo = xfrm_state_afinfo[family];
178 if (unlikely(!afinfo))
179 write_unlock_bh(&xfrm_state_afinfo_lock);
180 return afinfo;
181}
182
183static void xfrm_state_unlock_afinfo(struct xfrm_state_afinfo *afinfo)
184 __releases(xfrm_state_afinfo_lock)
185{
186 write_unlock_bh(&xfrm_state_afinfo_lock);
187}
188
189int xfrm_register_type(const struct xfrm_type *type, unsigned short family) 172int xfrm_register_type(const struct xfrm_type *type, unsigned short family)
190{ 173{
191 struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); 174 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
192 const struct xfrm_type **typemap; 175 const struct xfrm_type **typemap;
193 int err = 0; 176 int err = 0;
194 177
195 if (unlikely(afinfo == NULL)) 178 if (unlikely(afinfo == NULL))
196 return -EAFNOSUPPORT; 179 return -EAFNOSUPPORT;
197 typemap = afinfo->type_map; 180 typemap = afinfo->type_map;
181 spin_lock_bh(&xfrm_type_lock);
198 182
199 if (likely(typemap[type->proto] == NULL)) 183 if (likely(typemap[type->proto] == NULL))
200 typemap[type->proto] = type; 184 typemap[type->proto] = type;
201 else 185 else
202 err = -EEXIST; 186 err = -EEXIST;
203 xfrm_state_unlock_afinfo(afinfo); 187 spin_unlock_bh(&xfrm_type_lock);
188 xfrm_state_put_afinfo(afinfo);
204 return err; 189 return err;
205} 190}
206EXPORT_SYMBOL(xfrm_register_type); 191EXPORT_SYMBOL(xfrm_register_type);
207 192
208int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family) 193int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family)
209{ 194{
210 struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); 195 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
211 const struct xfrm_type **typemap; 196 const struct xfrm_type **typemap;
212 int err = 0; 197 int err = 0;
213 198
214 if (unlikely(afinfo == NULL)) 199 if (unlikely(afinfo == NULL))
215 return -EAFNOSUPPORT; 200 return -EAFNOSUPPORT;
216 typemap = afinfo->type_map; 201 typemap = afinfo->type_map;
202 spin_lock_bh(&xfrm_type_lock);
217 203
218 if (unlikely(typemap[type->proto] != type)) 204 if (unlikely(typemap[type->proto] != type))
219 err = -ENOENT; 205 err = -ENOENT;
220 else 206 else
221 typemap[type->proto] = NULL; 207 typemap[type->proto] = NULL;
222 xfrm_state_unlock_afinfo(afinfo); 208 spin_unlock_bh(&xfrm_type_lock);
209 xfrm_state_put_afinfo(afinfo);
223 return err; 210 return err;
224} 211}
225EXPORT_SYMBOL(xfrm_unregister_type); 212EXPORT_SYMBOL(xfrm_unregister_type);
@@ -256,6 +243,7 @@ static void xfrm_put_type(const struct xfrm_type *type)
256 module_put(type->owner); 243 module_put(type->owner);
257} 244}
258 245
246static DEFINE_SPINLOCK(xfrm_mode_lock);
259int xfrm_register_mode(struct xfrm_mode *mode, int family) 247int xfrm_register_mode(struct xfrm_mode *mode, int family)
260{ 248{
261 struct xfrm_state_afinfo *afinfo; 249 struct xfrm_state_afinfo *afinfo;
@@ -265,12 +253,13 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family)
265 if (unlikely(mode->encap >= XFRM_MODE_MAX)) 253 if (unlikely(mode->encap >= XFRM_MODE_MAX))
266 return -EINVAL; 254 return -EINVAL;
267 255
268 afinfo = xfrm_state_lock_afinfo(family); 256 afinfo = xfrm_state_get_afinfo(family);
269 if (unlikely(afinfo == NULL)) 257 if (unlikely(afinfo == NULL))
270 return -EAFNOSUPPORT; 258 return -EAFNOSUPPORT;
271 259
272 err = -EEXIST; 260 err = -EEXIST;
273 modemap = afinfo->mode_map; 261 modemap = afinfo->mode_map;
262 spin_lock_bh(&xfrm_mode_lock);
274 if (modemap[mode->encap]) 263 if (modemap[mode->encap])
275 goto out; 264 goto out;
276 265
@@ -283,7 +272,8 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family)
283 err = 0; 272 err = 0;
284 273
285out: 274out:
286 xfrm_state_unlock_afinfo(afinfo); 275 spin_unlock_bh(&xfrm_mode_lock);
276 xfrm_state_put_afinfo(afinfo);
287 return err; 277 return err;
288} 278}
289EXPORT_SYMBOL(xfrm_register_mode); 279EXPORT_SYMBOL(xfrm_register_mode);
@@ -297,19 +287,21 @@ int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
297 if (unlikely(mode->encap >= XFRM_MODE_MAX)) 287 if (unlikely(mode->encap >= XFRM_MODE_MAX))
298 return -EINVAL; 288 return -EINVAL;
299 289
300 afinfo = xfrm_state_lock_afinfo(family); 290 afinfo = xfrm_state_get_afinfo(family);
301 if (unlikely(afinfo == NULL)) 291 if (unlikely(afinfo == NULL))
302 return -EAFNOSUPPORT; 292 return -EAFNOSUPPORT;
303 293
304 err = -ENOENT; 294 err = -ENOENT;
305 modemap = afinfo->mode_map; 295 modemap = afinfo->mode_map;
296 spin_lock_bh(&xfrm_mode_lock);
306 if (likely(modemap[mode->encap] == mode)) { 297 if (likely(modemap[mode->encap] == mode)) {
307 modemap[mode->encap] = NULL; 298 modemap[mode->encap] = NULL;
308 module_put(mode->afinfo->owner); 299 module_put(mode->afinfo->owner);
309 err = 0; 300 err = 0;
310 } 301 }
311 302
312 xfrm_state_unlock_afinfo(afinfo); 303 spin_unlock_bh(&xfrm_mode_lock);
304 xfrm_state_put_afinfo(afinfo);
313 return err; 305 return err;
314} 306}
315EXPORT_SYMBOL(xfrm_unregister_mode); 307EXPORT_SYMBOL(xfrm_unregister_mode);
@@ -1370,9 +1362,6 @@ int xfrm_state_check_expire(struct xfrm_state *x)
1370 if (!x->curlft.use_time) 1362 if (!x->curlft.use_time)
1371 x->curlft.use_time = get_seconds(); 1363 x->curlft.use_time = get_seconds();
1372 1364
1373 if (x->km.state != XFRM_STATE_VALID)
1374 return -EINVAL;
1375
1376 if (x->curlft.bytes >= x->lft.hard_byte_limit || 1365 if (x->curlft.bytes >= x->lft.hard_byte_limit ||
1377 x->curlft.packets >= x->lft.hard_packet_limit) { 1366 x->curlft.packets >= x->lft.hard_packet_limit) {
1378 x->km.state = XFRM_STATE_EXPIRED; 1367 x->km.state = XFRM_STATE_EXPIRED;
@@ -1648,27 +1637,26 @@ static void xfrm_replay_timer_handler(unsigned long data)
1648} 1637}
1649 1638
1650static LIST_HEAD(xfrm_km_list); 1639static LIST_HEAD(xfrm_km_list);
1651static DEFINE_RWLOCK(xfrm_km_lock);
1652 1640
1653void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) 1641void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
1654{ 1642{
1655 struct xfrm_mgr *km; 1643 struct xfrm_mgr *km;
1656 1644
1657 read_lock(&xfrm_km_lock); 1645 rcu_read_lock();
1658 list_for_each_entry(km, &xfrm_km_list, list) 1646 list_for_each_entry_rcu(km, &xfrm_km_list, list)
1659 if (km->notify_policy) 1647 if (km->notify_policy)
1660 km->notify_policy(xp, dir, c); 1648 km->notify_policy(xp, dir, c);
1661 read_unlock(&xfrm_km_lock); 1649 rcu_read_unlock();
1662} 1650}
1663 1651
1664void km_state_notify(struct xfrm_state *x, const struct km_event *c) 1652void km_state_notify(struct xfrm_state *x, const struct km_event *c)
1665{ 1653{
1666 struct xfrm_mgr *km; 1654 struct xfrm_mgr *km;
1667 read_lock(&xfrm_km_lock); 1655 rcu_read_lock();
1668 list_for_each_entry(km, &xfrm_km_list, list) 1656 list_for_each_entry_rcu(km, &xfrm_km_list, list)
1669 if (km->notify) 1657 if (km->notify)
1670 km->notify(x, c); 1658 km->notify(x, c);
1671 read_unlock(&xfrm_km_lock); 1659 rcu_read_unlock();
1672} 1660}
1673 1661
1674EXPORT_SYMBOL(km_policy_notify); 1662EXPORT_SYMBOL(km_policy_notify);
@@ -1698,13 +1686,13 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
1698 int err = -EINVAL, acqret; 1686 int err = -EINVAL, acqret;
1699 struct xfrm_mgr *km; 1687 struct xfrm_mgr *km;
1700 1688
1701 read_lock(&xfrm_km_lock); 1689 rcu_read_lock();
1702 list_for_each_entry(km, &xfrm_km_list, list) { 1690 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1703 acqret = km->acquire(x, t, pol); 1691 acqret = km->acquire(x, t, pol);
1704 if (!acqret) 1692 if (!acqret)
1705 err = acqret; 1693 err = acqret;
1706 } 1694 }
1707 read_unlock(&xfrm_km_lock); 1695 rcu_read_unlock();
1708 return err; 1696 return err;
1709} 1697}
1710EXPORT_SYMBOL(km_query); 1698EXPORT_SYMBOL(km_query);
@@ -1714,14 +1702,14 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
1714 int err = -EINVAL; 1702 int err = -EINVAL;
1715 struct xfrm_mgr *km; 1703 struct xfrm_mgr *km;
1716 1704
1717 read_lock(&xfrm_km_lock); 1705 rcu_read_lock();
1718 list_for_each_entry(km, &xfrm_km_list, list) { 1706 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1719 if (km->new_mapping) 1707 if (km->new_mapping)
1720 err = km->new_mapping(x, ipaddr, sport); 1708 err = km->new_mapping(x, ipaddr, sport);
1721 if (!err) 1709 if (!err)
1722 break; 1710 break;
1723 } 1711 }
1724 read_unlock(&xfrm_km_lock); 1712 rcu_read_unlock();
1725 return err; 1713 return err;
1726} 1714}
1727EXPORT_SYMBOL(km_new_mapping); 1715EXPORT_SYMBOL(km_new_mapping);
@@ -1750,15 +1738,15 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
1750 int ret; 1738 int ret;
1751 struct xfrm_mgr *km; 1739 struct xfrm_mgr *km;
1752 1740
1753 read_lock(&xfrm_km_lock); 1741 rcu_read_lock();
1754 list_for_each_entry(km, &xfrm_km_list, list) { 1742 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1755 if (km->migrate) { 1743 if (km->migrate) {
1756 ret = km->migrate(sel, dir, type, m, num_migrate, k); 1744 ret = km->migrate(sel, dir, type, m, num_migrate, k);
1757 if (!ret) 1745 if (!ret)
1758 err = ret; 1746 err = ret;
1759 } 1747 }
1760 } 1748 }
1761 read_unlock(&xfrm_km_lock); 1749 rcu_read_unlock();
1762 return err; 1750 return err;
1763} 1751}
1764EXPORT_SYMBOL(km_migrate); 1752EXPORT_SYMBOL(km_migrate);
@@ -1770,15 +1758,15 @@ int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address
1770 int ret; 1758 int ret;
1771 struct xfrm_mgr *km; 1759 struct xfrm_mgr *km;
1772 1760
1773 read_lock(&xfrm_km_lock); 1761 rcu_read_lock();
1774 list_for_each_entry(km, &xfrm_km_list, list) { 1762 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1775 if (km->report) { 1763 if (km->report) {
1776 ret = km->report(net, proto, sel, addr); 1764 ret = km->report(net, proto, sel, addr);
1777 if (!ret) 1765 if (!ret)
1778 err = ret; 1766 err = ret;
1779 } 1767 }
1780 } 1768 }
1781 read_unlock(&xfrm_km_lock); 1769 rcu_read_unlock();
1782 return err; 1770 return err;
1783} 1771}
1784EXPORT_SYMBOL(km_report); 1772EXPORT_SYMBOL(km_report);
@@ -1802,14 +1790,14 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
1802 goto out; 1790 goto out;
1803 1791
1804 err = -EINVAL; 1792 err = -EINVAL;
1805 read_lock(&xfrm_km_lock); 1793 rcu_read_lock();
1806 list_for_each_entry(km, &xfrm_km_list, list) { 1794 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1807 pol = km->compile_policy(sk, optname, data, 1795 pol = km->compile_policy(sk, optname, data,
1808 optlen, &err); 1796 optlen, &err);
1809 if (err >= 0) 1797 if (err >= 0)
1810 break; 1798 break;
1811 } 1799 }
1812 read_unlock(&xfrm_km_lock); 1800 rcu_read_unlock();
1813 1801
1814 if (err >= 0) { 1802 if (err >= 0) {
1815 xfrm_sk_policy_insert(sk, err, pol); 1803 xfrm_sk_policy_insert(sk, err, pol);
@@ -1823,20 +1811,23 @@ out:
1823} 1811}
1824EXPORT_SYMBOL(xfrm_user_policy); 1812EXPORT_SYMBOL(xfrm_user_policy);
1825 1813
1814static DEFINE_SPINLOCK(xfrm_km_lock);
1815
1826int xfrm_register_km(struct xfrm_mgr *km) 1816int xfrm_register_km(struct xfrm_mgr *km)
1827{ 1817{
1828 write_lock_bh(&xfrm_km_lock); 1818 spin_lock_bh(&xfrm_km_lock);
1829 list_add_tail(&km->list, &xfrm_km_list); 1819 list_add_tail_rcu(&km->list, &xfrm_km_list);
1830 write_unlock_bh(&xfrm_km_lock); 1820 spin_unlock_bh(&xfrm_km_lock);
1831 return 0; 1821 return 0;
1832} 1822}
1833EXPORT_SYMBOL(xfrm_register_km); 1823EXPORT_SYMBOL(xfrm_register_km);
1834 1824
1835int xfrm_unregister_km(struct xfrm_mgr *km) 1825int xfrm_unregister_km(struct xfrm_mgr *km)
1836{ 1826{
1837 write_lock_bh(&xfrm_km_lock); 1827 spin_lock_bh(&xfrm_km_lock);
1838 list_del(&km->list); 1828 list_del_rcu(&km->list);
1839 write_unlock_bh(&xfrm_km_lock); 1829 spin_unlock_bh(&xfrm_km_lock);
1830 synchronize_rcu();
1840 return 0; 1831 return 0;
1841} 1832}
1842EXPORT_SYMBOL(xfrm_unregister_km); 1833EXPORT_SYMBOL(xfrm_unregister_km);
@@ -1848,12 +1839,12 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
1848 return -EINVAL; 1839 return -EINVAL;
1849 if (unlikely(afinfo->family >= NPROTO)) 1840 if (unlikely(afinfo->family >= NPROTO))
1850 return -EAFNOSUPPORT; 1841 return -EAFNOSUPPORT;
1851 write_lock_bh(&xfrm_state_afinfo_lock); 1842 spin_lock_bh(&xfrm_state_afinfo_lock);
1852 if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) 1843 if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
1853 err = -ENOBUFS; 1844 err = -ENOBUFS;
1854 else 1845 else
1855 xfrm_state_afinfo[afinfo->family] = afinfo; 1846 rcu_assign_pointer(xfrm_state_afinfo[afinfo->family], afinfo);
1856 write_unlock_bh(&xfrm_state_afinfo_lock); 1847 spin_unlock_bh(&xfrm_state_afinfo_lock);
1857 return err; 1848 return err;
1858} 1849}
1859EXPORT_SYMBOL(xfrm_state_register_afinfo); 1850EXPORT_SYMBOL(xfrm_state_register_afinfo);
@@ -1865,14 +1856,15 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
1865 return -EINVAL; 1856 return -EINVAL;
1866 if (unlikely(afinfo->family >= NPROTO)) 1857 if (unlikely(afinfo->family >= NPROTO))
1867 return -EAFNOSUPPORT; 1858 return -EAFNOSUPPORT;
1868 write_lock_bh(&xfrm_state_afinfo_lock); 1859 spin_lock_bh(&xfrm_state_afinfo_lock);
1869 if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) { 1860 if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {
1870 if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo)) 1861 if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
1871 err = -EINVAL; 1862 err = -EINVAL;
1872 else 1863 else
1873 xfrm_state_afinfo[afinfo->family] = NULL; 1864 RCU_INIT_POINTER(xfrm_state_afinfo[afinfo->family], NULL);
1874 } 1865 }
1875 write_unlock_bh(&xfrm_state_afinfo_lock); 1866 spin_unlock_bh(&xfrm_state_afinfo_lock);
1867 synchronize_rcu();
1876 return err; 1868 return err;
1877} 1869}
1878EXPORT_SYMBOL(xfrm_state_unregister_afinfo); 1870EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
@@ -1882,17 +1874,16 @@ static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
1882 struct xfrm_state_afinfo *afinfo; 1874 struct xfrm_state_afinfo *afinfo;
1883 if (unlikely(family >= NPROTO)) 1875 if (unlikely(family >= NPROTO))
1884 return NULL; 1876 return NULL;
1885 read_lock(&xfrm_state_afinfo_lock); 1877 rcu_read_lock();
1886 afinfo = xfrm_state_afinfo[family]; 1878 afinfo = rcu_dereference(xfrm_state_afinfo[family]);
1887 if (unlikely(!afinfo)) 1879 if (unlikely(!afinfo))
1888 read_unlock(&xfrm_state_afinfo_lock); 1880 rcu_read_unlock();
1889 return afinfo; 1881 return afinfo;
1890} 1882}
1891 1883
1892static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) 1884static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
1893 __releases(xfrm_state_afinfo_lock)
1894{ 1885{
1895 read_unlock(&xfrm_state_afinfo_lock); 1886 rcu_read_unlock();
1896} 1887}
1897 1888
1898/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */ 1889/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */