summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/team/team_mode_loadbalance.c6
-rw-r--r--net/core/filter.c11
2 files changed, 13 insertions, 4 deletions
diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c
index a58dfebb5512..7106f3456439 100644
--- a/drivers/net/team/team_mode_loadbalance.c
+++ b/drivers/net/team/team_mode_loadbalance.c
@@ -293,11 +293,15 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx)
__fprog_destroy(lb_priv->ex->orig_fprog);
orig_fp = rcu_dereference_protected(lb_priv->fp,
lockdep_is_held(&team->lock));
- sk_unattached_filter_destroy(orig_fp);
}
rcu_assign_pointer(lb_priv->fp, fp);
lb_priv->ex->orig_fprog = fprog;
+
+ if (orig_fp) {
+ synchronize_rcu();
+ sk_unattached_filter_destroy(orig_fp);
+ }
return 0;
}
diff --git a/net/core/filter.c b/net/core/filter.c
index f3b2d5e9fe5f..42c1944b0c63 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -841,6 +841,12 @@ static void sk_release_orig_filter(struct sk_filter *fp)
}
}
+static void __sk_filter_release(struct sk_filter *fp)
+{
+ sk_release_orig_filter(fp);
+ sk_filter_free(fp);
+}
+
/**
* sk_filter_release_rcu - Release a socket filter by rcu_head
* @rcu: rcu_head that contains the sk_filter to free
@@ -849,8 +855,7 @@ static void sk_filter_release_rcu(struct rcu_head *rcu)
{
struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
- sk_release_orig_filter(fp);
- sk_filter_free(fp);
+ __sk_filter_release(fp);
}
/**
@@ -1050,7 +1055,7 @@ EXPORT_SYMBOL_GPL(sk_unattached_filter_create);
void sk_unattached_filter_destroy(struct sk_filter *fp)
{
- sk_filter_release(fp);
+ __sk_filter_release(fp);
}
EXPORT_SYMBOL_GPL(sk_unattached_filter_destroy);