Message ID | 20221214103857.69082-1-xiangxia.m.yue@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | [bpf-next,1/2] bpf: hash map, avoid deadlock with suitable hash mask | expand |
On 12/14/22 2:38 AM, xiangxia.m.yue@gmail.com wrote: > From: Tonghao Zhang <xiangxia.m.yue@gmail.com> > > The deadlock still may occur while accessed in NMI and non-NMI > context. Because in NMI, we still may access the same bucket but with > different map_locked index. > > For example, on the same CPU, .max_entries = 2, we update the hash map, > with key = 4, while running bpf prog in NMI nmi_handle(), to update > hash map with key = 20, so it will have the same bucket index but have > different map_locked index. > > To fix this issue, using min mask to hash again. > > Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com> > Cc: Alexei Starovoitov <ast@kernel.org> > Cc: Daniel Borkmann <daniel@iogearbox.net> > Cc: Andrii Nakryiko <andrii@kernel.org> > Cc: Martin KaFai Lau <martin.lau@linux.dev> > Cc: Song Liu <song@kernel.org> > Cc: Yonghong Song <yhs@fb.com> > Cc: John Fastabend <john.fastabend@gmail.com> > Cc: KP Singh <kpsingh@kernel.org> > Cc: Stanislav Fomichev <sdf@google.com> > Cc: Hao Luo <haoluo@google.com> > Cc: Jiri Olsa <jolsa@kernel.org> > Cc: Hou Tao <houtao1@huawei.com> Acked-by: Yonghong Song <yhs@fb.com>
Hi, On 12/14/2022 6:38 PM, xiangxia.m.yue@gmail.com wrote: > From: Tonghao Zhang <xiangxia.m.yue@gmail.com> > > The deadlock still may occur while accessed in NMI and non-NMI > context. Because in NMI, we still may access the same bucket but with > different map_locked index. > > For example, on the same CPU, .max_entries = 2, we update the hash map, > with key = 4, while running bpf prog in NMI nmi_handle(), to update > hash map with key = 20, so it will have the same bucket index but have > different map_locked index. > > To fix this issue, using min mask to hash again. > > Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com> > Cc: Alexei Starovoitov <ast@kernel.org> > Cc: Daniel Borkmann <daniel@iogearbox.net> > Cc: Andrii Nakryiko <andrii@kernel.org> > Cc: Martin KaFai Lau <martin.lau@linux.dev> > Cc: Song Liu <song@kernel.org> > Cc: Yonghong Song <yhs@fb.com> > Cc: John Fastabend <john.fastabend@gmail.com> > Cc: KP Singh <kpsingh@kernel.org> > Cc: Stanislav Fomichev <sdf@google.com> > Cc: Hao Luo <haoluo@google.com> > Cc: Jiri Olsa <jolsa@kernel.org> > Cc: Hou Tao <houtao1@huawei.com> > --- > kernel/bpf/hashtab.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c > index 5aa2b5525f79..8b25036a8690 100644 > --- a/kernel/bpf/hashtab.c > +++ b/kernel/bpf/hashtab.c > @@ -152,7 +152,7 @@ static inline int htab_lock_bucket(const struct bpf_htab *htab, > { > unsigned long flags; > > - hash = hash & HASHTAB_MAP_LOCK_MASK; > + hash = hash & min(HASHTAB_MAP_LOCK_MASK, htab->n_buckets -1); There is warning for kernel test robot and it seems that min_t(...) is required here. Otherwise, this patch looks good to me, so: Acked-by: Hou Tao <houtao1@huawei.com> > > preempt_disable(); > if (unlikely(__this_cpu_inc_return(*(htab->map_locked[hash])) != 1)) { > @@ -171,7 +171,7 @@ static inline void htab_unlock_bucket(const struct bpf_htab *htab, > struct bucket *b, u32 hash, > unsigned long flags) > { > - hash = hash & HASHTAB_MAP_LOCK_MASK; > + hash = hash & min(HASHTAB_MAP_LOCK_MASK, htab->n_buckets -1); > raw_spin_unlock_irqrestore(&b->raw_lock, flags); > __this_cpu_dec(*(htab->map_locked[hash])); > preempt_enable();
On Fri, Dec 16, 2022 at 6:15 PM Hou Tao <houtao1@huawei.com> wrote: > > Hi, > > On 12/14/2022 6:38 PM, xiangxia.m.yue@gmail.com wrote: > > From: Tonghao Zhang <xiangxia.m.yue@gmail.com> > > > > The deadlock still may occur while accessed in NMI and non-NMI > > context. Because in NMI, we still may access the same bucket but with > > different map_locked index. > > > > For example, on the same CPU, .max_entries = 2, we update the hash map, > > with key = 4, while running bpf prog in NMI nmi_handle(), to update > > hash map with key = 20, so it will have the same bucket index but have > > different map_locked index. > > > > To fix this issue, using min mask to hash again. > > > > Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com> > > Cc: Alexei Starovoitov <ast@kernel.org> > > Cc: Daniel Borkmann <daniel@iogearbox.net> > > Cc: Andrii Nakryiko <andrii@kernel.org> > > Cc: Martin KaFai Lau <martin.lau@linux.dev> > > Cc: Song Liu <song@kernel.org> > > Cc: Yonghong Song <yhs@fb.com> > > Cc: John Fastabend <john.fastabend@gmail.com> > > Cc: KP Singh <kpsingh@kernel.org> > > Cc: Stanislav Fomichev <sdf@google.com> > > Cc: Hao Luo <haoluo@google.com> > > Cc: Jiri Olsa <jolsa@kernel.org> > > Cc: Hou Tao <houtao1@huawei.com> > > --- > > kernel/bpf/hashtab.c | 4 ++-- > > 1 file changed, 2 insertions(+), 2 deletions(-) > > > > diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c > > index 5aa2b5525f79..8b25036a8690 100644 > > --- a/kernel/bpf/hashtab.c > > +++ b/kernel/bpf/hashtab.c > > @@ -152,7 +152,7 @@ static inline int htab_lock_bucket(const struct bpf_htab *htab, > > { > > unsigned long flags; > > > > - hash = hash & HASHTAB_MAP_LOCK_MASK; > > + hash = hash & min(HASHTAB_MAP_LOCK_MASK, htab->n_buckets -1); > There is warning for kernel test robot and it seems that min_t(...) is required I will send v2 soon. Thanks. > here. > > Otherwise, this patch looks good to me, so: > > Acked-by: Hou Tao <houtao1@huawei.com> > > > > preempt_disable(); > > if (unlikely(__this_cpu_inc_return(*(htab->map_locked[hash])) != 1)) { > > @@ -171,7 +171,7 @@ static inline void htab_unlock_bucket(const struct bpf_htab *htab, > > struct bucket *b, u32 hash, > > unsigned long flags) > > { > > - hash = hash & HASHTAB_MAP_LOCK_MASK; > > + hash = hash & min(HASHTAB_MAP_LOCK_MASK, htab->n_buckets -1); > > raw_spin_unlock_irqrestore(&b->raw_lock, flags); > > __this_cpu_dec(*(htab->map_locked[hash])); > > preempt_enable(); >
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index 5aa2b5525f79..8b25036a8690 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -152,7 +152,7 @@ static inline int htab_lock_bucket(const struct bpf_htab *htab, { unsigned long flags; - hash = hash & HASHTAB_MAP_LOCK_MASK; + hash = hash & min(HASHTAB_MAP_LOCK_MASK, htab->n_buckets -1); preempt_disable(); if (unlikely(__this_cpu_inc_return(*(htab->map_locked[hash])) != 1)) { @@ -171,7 +171,7 @@ static inline void htab_unlock_bucket(const struct bpf_htab *htab, struct bucket *b, u32 hash, unsigned long flags) { - hash = hash & HASHTAB_MAP_LOCK_MASK; + hash = hash & min(HASHTAB_MAP_LOCK_MASK, htab->n_buckets -1); raw_spin_unlock_irqrestore(&b->raw_lock, flags); __this_cpu_dec(*(htab->map_locked[hash])); preempt_enable();