|
@@ -55,11 +55,15 @@ MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
|
|
MODULE_DESCRIPTION("core IP set support");
|
|
|
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
|
|
|
|
|
|
-/* When the nfnl mutex is held: */
|
|
|
+/* When the nfnl mutex or ip_set_ref_lock is held: */
|
|
|
#define ip_set_dereference(p) \
|
|
|
- rcu_dereference_protected(p, lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET))
|
|
|
+ rcu_dereference_protected(p, \
|
|
|
+ lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \
|
|
|
+ lockdep_is_held(&ip_set_ref_lock))
|
|
|
#define ip_set(inst, id) \
|
|
|
ip_set_dereference((inst)->ip_set_list)[id]
|
|
|
+#define ip_set_ref_netlink(inst,id) \
|
|
|
+ rcu_dereference_raw((inst)->ip_set_list)[id]
|
|
|
|
|
|
/* The set types are implemented in modules and registered set types
|
|
|
* can be found in ip_set_type_list. Adding/deleting types is
|
|
@@ -1251,7 +1255,7 @@ ip_set_dump_done(struct netlink_callback *cb)
|
|
|
struct ip_set_net *inst =
|
|
|
(struct ip_set_net *)cb->args[IPSET_CB_NET];
|
|
|
ip_set_id_t index = (ip_set_id_t)cb->args[IPSET_CB_INDEX];
|
|
|
- struct ip_set *set = ip_set(inst, index);
|
|
|
+ struct ip_set *set = ip_set_ref_netlink(inst, index);
|
|
|
|
|
|
if (set->variant->uref)
|
|
|
set->variant->uref(set, cb, false);
|
|
@@ -1440,7 +1444,7 @@ next_set:
|
|
|
release_refcount:
|
|
|
/* If there was an error or set is done, release set */
|
|
|
if (ret || !cb->args[IPSET_CB_ARG0]) {
|
|
|
- set = ip_set(inst, index);
|
|
|
+ set = ip_set_ref_netlink(inst, index);
|
|
|
if (set->variant->uref)
|
|
|
set->variant->uref(set, cb, false);
|
|
|
pr_debug("release set %s\n", set->name);
|