]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
bpf: Free special fields after unlock in htab_lru_map_delete_node()
authorHou Tao <houtao1@huawei.com>
Fri, 17 Jan 2025 10:18:12 +0000 (18:18 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Mon, 20 Jan 2025 17:09:01 +0000 (09:09 -0800)
When bpf_timer is used in LRU hash map, calling check_and_free_fields()
in htab_lru_map_delete_node() will invoke bpf_timer_cancel_and_free() to
free the bpf_timer. If the timer is running on other CPUs,
hrtimer_cancel() will invoke hrtimer_cancel_wait_running() to spin on
current CPU to wait for the completion of the hrtimer callback.

Considering that the deletion has already acquired a raw-spin-lock
(bucket lock). To reduce the time holding the bucket lock, move the
invocation of check_and_free_fields() out of bucket lock. However,
because htab_lru_map_delete_node() is invoked with LRU raw spin lock
being held, the freeing of special fields still happens in a locked
scope.

Signed-off-by: Hou Tao <houtao1@huawei.com>
Reviewed-by: Toke Høiland-Jørgensen <toke@kernel.org>
Link: https://lore.kernel.org/r/20250117101816.2101857-2-houtao@huaweicloud.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/hashtab.c

index 40095dda891d31846aef832e27c9f77759e23cf2..963cccb01daae380cdeb6bf32b94e5069bd06301 100644 (file)
@@ -824,13 +824,14 @@ static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node)
        hlist_nulls_for_each_entry_rcu(l, n, head, hash_node)
                if (l == tgt_l) {
                        hlist_nulls_del_rcu(&l->hash_node);
-                       check_and_free_fields(htab, l);
                        bpf_map_dec_elem_count(&htab->map);
                        break;
                }
 
        htab_unlock_bucket(htab, b, tgt_l->hash, flags);
 
+       if (l == tgt_l)
+               check_and_free_fields(htab, l);
        return l == tgt_l;
 }