If a key is deleted after a batch copies it, rhashtable_next_key() returns ERR_PTR(-ENOENT). The batch code treats the missing next cursor as end-of-iteration and returns -ENOENT with a partial batch, so callers can silently stop before reading keys that are still present. Translate a lost traversal key to -EAGAIN, as for a missing input cursor, and preserve other iterator errors. Still copy the collected entries and update the count, including for lookup-and-delete batches. Fixes: 818e00848227 ("bpf: Implement iteration ops for resizable hashtab") Link: https://github.com/kernel-patches/bpf/pull/14700#issuecomment-6641291019 Acked-by: Mykyta Yatsenko Assisted-by: LLM Signed-off-by: Tianyi Chen --- kernel/bpf/hashtab.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index 6e2115477cb9..346a2afb4ad3 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -3556,14 +3556,15 @@ static int __rhtab_map_lookup_and_delete_batch(struct bpf_map *map, rcu_read_unlock(); - if (total == 0) { + if (IS_ERR(elem)) { + ret = PTR_ERR(elem); + if (ret == -ENOENT) + ret = -EAGAIN; + } else if (!has_next_cursor) { ret = -ENOENT; - goto free; } - - /* No more elements after this batch. */ - if (!has_next_cursor) - ret = -ENOENT; + if (!total) + goto free; if (copy_to_user(ukeys, keys, (size_t)total * key_size) || copy_to_user(uvalues, values, (size_t)total * value_size) || -- 2.56.0