From nobody Sat Feb 7 23:24:40 2026 Received: from mail-qv1-f43.google.com (mail-qv1-f43.google.com [209.85.219.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F1EC2185924 for ; Fri, 7 Feb 2025 05:45:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738907122; cv=none; b=qXz7G/oC7541pL1NMSYioJKCjJ8TtFBzJhLxNFeB4SLOCiMi0MSAl9kToucCwNLckZkifYz/ahimXQpRHFe0nKZRjtxx9ChB+vpqwSdy712/SvmPtL1wjXS52Ben7LNTIJHnWy9LMA7N0fJ/RlJwq5kktMI+4gLwaI2KmhQclsg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738907122; c=relaxed/simple; bh=x61C/F4J/oG3FG1KFD20Za19v9HG288Z19JPSbWmAMI=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=r3xikzj7hxX2ZOdYVI+yt/xwEzR5mwpdoxep/ECtrWBKe4K7qPoHzYGlLvr0i/gtvuCYsf/3SlfECJx6xtiH6XcUEgVTGhkN6BIIXvcyAgzDoFsEBtqq5pc4TNIhZvuXDrs37mzVxTNnH2trTfrN5AdwlbEGeuMCPpHg19C383g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cloudflare.com; spf=pass smtp.mailfrom=cloudflare.com; dkim=pass (2048-bit key) header.d=cloudflare.com header.i=@cloudflare.com header.b=Rski2O3F; arc=none smtp.client-ip=209.85.219.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cloudflare.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cloudflare.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cloudflare.com header.i=@cloudflare.com header.b="Rski2O3F" Received: by mail-qv1-f43.google.com with SMTP id 6a1803df08f44-6dcd4f1aaccso27632206d6.2 for ; Thu, 06 Feb 2025 21:45:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google09082023; t=1738907120; x=1739511920; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=MPMcU7relN033a1ztg4Vj2Rf/KyzQJjjuQ/8o89cp7k=; b=Rski2O3Fs1cxOgik6Hjyhi9grCRj5cgcx+diKvtCP7QxwDeVEYStfoWukXqQN9swbB LeWoMCdlzsLB4UBcbeUTg685aLuKFf+zejzdpVbhhDh1fxeJxkZcEuYgvHT3b0czkQGZ glTr9E0N07yK1aP3qHM4gIZeFk8RCa3PzQSfR2nbloaA4feXPCJEUaG8i6qJxFxGevvD IB16NXb1rwvEve2Eo73tOchMfVmroJlC5oJ2A/PsuVFIQrIjqAroYtvR0cCwedZg2H78 7pas46gbQWLLlZTpUUBHNF24mvAqAB7172CtCyDC5PKi6w8Ba5plcSQBLkmDRSQDB0hZ X1EA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738907120; x=1739511920; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=MPMcU7relN033a1ztg4Vj2Rf/KyzQJjjuQ/8o89cp7k=; b=bcyABiD58KumymJVoVKSo29f5NJ17CnYoEdYFeLySjDr0CvJO/eOcQ6LHoUsvr71Al jbbA5sDDrqQUXQzdDh4hMpPbRNhbGy+X8ptT5xs5/DlvoL0XRlr/Nyt7lqOnTlCqa/fD YWhWnyoIm3Dw/cVsxhrqSrJVI2gSdyp0U5prNqkGRkPB8jYyYEQOeKmAtTYxuHYXyb6A blrQcJVh0+wSHtm8mbt3tgkynivPZ5cyUqv1iO4U+11pLMu+87cUYmBCdDlgHzIZEa6O JJOOxSCG51aoAm9VlNXsBq/jrYQ1ORcP+0sYz0f3xFpcFwP08xGlWDgKoEDCE8Vaj4i2 c6HQ== X-Forwarded-Encrypted: i=1; AJvYcCV7SjzGKtOIMfltlWspKjaJOAlvimOupH8+2HDEwtuFdl5LltwGU4Kmd9K8IpVuwBRaFWkqsa/HCpgZD/o=@vger.kernel.org X-Gm-Message-State: AOJu0YyEwAkN0PwAVo4YNfoX4KIWOmfwoMPYkYGmrHMk2AbGZL0GAzH8 II3SRxZBTZGw/jW5kmReCA2ER1Pn4Z9IWWE9efjuYMFMJxt2kHjolsM85IWFitc= X-Gm-Gg: ASbGncsDgK3D+dsD5eYqSshKvyNxVPUx0DLoW9QsI5PL6Dj8XB+RDx992s5kcTYFMDa TPm0bg0dGl+K3UI5ggYoQbI+4VLYdOY6HQCKUtTkX6HEceU/c1/L75zMNnkWmV5GEPGx40NIVTC ToZlfz0szpXAuCiCcB+YgmZQ8y9R5Ehl/hKHcWVCLq0itDsIDj/QFKP1wWoUPZ7+0C95a93tGYc iL4QbQP2pgpj0G4ZrSSdG5r+fuP+QnKOpuh1XXaNMtf2jyW2kkxqee4dYSw9I+qouzg8PGhtcTI +ko= X-Google-Smtp-Source: AGHT+IEMtX5bNJe8+qFygANCqnKDtR8huQvrBTgdMpqJiJ33srctAZXEpbmfeT9ktGaXGKTQzI09GQ== X-Received: by 2002:ad4:5fca:0:b0:6d8:932a:eaa3 with SMTP id 6a1803df08f44-6e4455d4541mr26654036d6.3.1738907119910; Thu, 06 Feb 2025 21:45:19 -0800 (PST) Received: from debian.debian ([2a09:bac5:79dd:25a5::3c0:2]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-6e43baacb5dsm13228256d6.88.2025.02.06.21.45.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Feb 2025 21:45:18 -0800 (PST) Date: Thu, 6 Feb 2025 21:45:16 -0800 From: Yan Zhai To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Mykola Lysenko , Shuah Khan , Yan Zhai , Brian Vazquez , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-team@cloudflare.com, Hou Tao Subject: [PATCH v2 bpf 1/2] bpf: skip non exist keys in generic_map_lookup_batch Message-ID: <177c4a3417d848aa9d72158e235be7d6b6f43915.1738905497.git.yan@cloudflare.com> References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The generic_map_lookup_batch currently returns EINTR if it fails with ENOENT and retries several times on bpf_map_copy_value. The next batch would start from the same location, presuming it's a transient issue. This is incorrect if a map can actually have "holes", i.e. "get_next_key" can return a key that does not point to a valid value. At least the array of maps type may contain such holes legitly. Right now these holes show up, generic batch lookup cannot proceed any more. It will always fail with EINTR errors. Rather, do not retry in generic_map_lookup_batch. If it finds a non existing element, skip to the next key. This simple solution comes with a price that transient errors may not be recovered, and the iteration might cycle back to the first key under parallel deletion. For example, Hou Tao pointed out a following scenario: For LPM trie map: (1) ->map_get_next_key(map, prev_key, key) returns a valid key (2) bpf_map_copy_value() return -ENOMENT It means the key must be deleted concurrently. (3) goto next_key It swaps the prev_key and key (4) ->map_get_next_key(map, prev_key, key) again prev_key points to a non-existing key, for LPM trie it will treat just like prev_key=3DNULL case, the returned key will be duplicated. With the retry logic, the iteration can continue to the key next to the deleted one. But if we directly skip to the next key, the iteration loop would restart from the first key for the lpm_trie type. However, not all races may be recovered. For example, if current key is deleted after instead of before bpf_map_copy_value, or if the prev_key also gets deleted, then the loop will still restart from the first key for lpm_tire anyway. For generic lookup it might be better to stay simple, i.e. just skip to the next key. To guarantee that the output keys are not duplicated, it is better to implement map type specific batch operations, which can properly lock the trie and synchronize with concurrent mutators. Fixes: cb4d03ab499d ("bpf: Add generic support for lookup batch op") Closes: https://lore.kernel.org/bpf/Z6JXtA1M5jAZx8xD@debian.debian/ Signed-off-by: Yan Zhai Acked-by: Hou Tao --- v1->v2: incorporate more useful information inside commit message. v1: https://lore.kernel.org/bpf/Z6OYbS4WqQnmzi2z@debian.debian/ --- kernel/bpf/syscall.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index c420edbfb7c8..5d0a4db6fb85 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1979,8 +1979,8 @@ int generic_map_lookup_batch(struct bpf_map *map, void __user *values =3D u64_to_user_ptr(attr->batch.values); void __user *keys =3D u64_to_user_ptr(attr->batch.keys); void *buf, *buf_prevkey, *prev_key, *key, *value; - int err, retry =3D MAP_LOOKUP_RETRIES; u32 value_size, cp, max_count; + int err; =20 if (attr->batch.elem_flags & ~BPF_F_LOCK) return -EINVAL; @@ -2026,14 +2026,8 @@ int generic_map_lookup_batch(struct bpf_map *map, err =3D bpf_map_copy_value(map, key, value, attr->batch.elem_flags); =20 - if (err =3D=3D -ENOENT) { - if (retry) { - retry--; - continue; - } - err =3D -EINTR; - break; - } + if (err =3D=3D -ENOENT) + goto next_key; =20 if (err) goto free_buf; @@ -2048,12 +2042,12 @@ int generic_map_lookup_batch(struct bpf_map *map, goto free_buf; } =20 + cp++; +next_key: if (!prev_key) prev_key =3D buf_prevkey; =20 swap(prev_key, key); - retry =3D MAP_LOOKUP_RETRIES; - cp++; cond_resched(); } =20 --=20 2.39.5 From nobody Sat Feb 7 23:24:40 2026 Received: from mail-qk1-f171.google.com (mail-qk1-f171.google.com [209.85.222.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8FF38233D8E for ; Fri, 7 Feb 2025 05:45:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738907126; cv=none; b=G8cjpNY3jnAhql9n0CFz7xfADI3K8T4b0Q1db2rIgAxkzYGn3kv3uz1ExiHr+/R1J9701i5eA9PZKOMfpnxMUVhiF/Xi8NMXP/zEVXmRlUX9TYl0VCngrGkCpA7tUo8gYpKnCFxavJpzjNCkjpHG60veTLDfTn55PiXgee9qRVc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738907126; c=relaxed/simple; bh=TSqw6WTzkGxJ2g7v2P63DZ+KseEhuRtpFe8QcAD65c0=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=OkrULn+zYDYyVF0HtXzzy1R5UqZdlM4FxxBB2O9T7qm2PtOin6YWFYooBBR8eKmsHEg6aQJZlz8Py+IisjdG2e5kgJ6uBy5K4gfSX26EYw/InkceVNcM4czbCXqi11EWHbROvbG8+b1X6gxV8WiVS9gBszVDRV2KPRfg9Wb0uPQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cloudflare.com; spf=pass smtp.mailfrom=cloudflare.com; dkim=pass (2048-bit key) header.d=cloudflare.com header.i=@cloudflare.com header.b=UHEPg4YV; arc=none smtp.client-ip=209.85.222.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cloudflare.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cloudflare.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cloudflare.com header.i=@cloudflare.com header.b="UHEPg4YV" Received: by mail-qk1-f171.google.com with SMTP id af79cd13be357-7b6eeff1fdfso146684085a.2 for ; Thu, 06 Feb 2025 21:45:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google09082023; t=1738907123; x=1739511923; darn=vger.kernel.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=BiL88Vl7FssHFuR4sgsTuWpUW3EZbuNKD07jWPDb1JA=; b=UHEPg4YVibcpTJ1mxaJRGLdhZvlvZ2EM/Z4sqsMsVLTNFTaB2r8peb7JBdIex/qYnw lK5vLlkMdjY+tqFSXvVOw2WSelcQ+KUb51Ho0dWExP4NnKMCFRdOAP7F+qX1hyyW4wD5 RIVDkAPbgqdMWSgeaDWSWU+IbwuFVEDj38tiSDNlZ5WuD1dC43q3doQNvVCaophJgEDN M7a9eyQma7FA72ofTx5y/50H6w0wtKVKm7p1pqzCXLnoMeddfD/uFzKnyPjSeklPNtgs eySYagC2xNcvtlDc6Vyk6pIUVuFpXtVHmsnM1iGYa5a2GZLgVGAhMRMThPKIqVqAJmvy jfZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738907123; x=1739511923; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=BiL88Vl7FssHFuR4sgsTuWpUW3EZbuNKD07jWPDb1JA=; b=PvDh2mnaznGE3Ilyu7p5AzJPtujBDMmR9CCosM814+yzcLWx0l6rLBBTEH/YAAhk/M WSR8yIsG4Q5EESecAXwH1X4mhYLf6uUgN9UYWakdRWYevBG2PXyJoO2liZlM3XvtW/AH aISE5TZNOHt0a5y/+6y06hqpqAMIKOn0ypYJwkNmUekRCSkRfjPQiJXChfUrfI0WCjDF RJEpVKPnP+FLTVNlwRFxomsywzKsMc3MEMvGjtnKh1vQnqWrpo2h7/ZfDBLPgBNm2Z3N 9pg0m0p9pnhcLx35Cbqse/9PbxTuVdwm1HX4+d6gfftXCrHL1q83ah5SdcPUY1CJUprg lCTg== X-Forwarded-Encrypted: i=1; AJvYcCW4qs7vS0b6TXyl0nGHvYnWV5+/wKuWnfhIcTRzJ8p95+LKWskGI9FtSDGBpVv6ym4P0RouZUUwpq4eSfM=@vger.kernel.org X-Gm-Message-State: AOJu0YxJjdVzXrYOucpU+MEaJG8ibKR9u8mBYaYr6MtNA8EhseaBF3vc d9/6eAs/Wdxiv4cWp8YuNp37bY5q7fIIRckQ7ifsVlyrtXSm84kOK006UB5rW10= X-Gm-Gg: ASbGncsQiNJ4JqfWCIulM2+Me4ripzKsXkvjDJP5/3DdhNbwLiJL+WOV9PR4wiXNr7t j4slbEvfC589Rn18LhrMQD4sr4TXICkGMuN1f0Bo9m5EPSwFVyK5Y2beiYh8bk2xvNnwzQ3eBmw vKup/wYzXEXpFOYK02fsii5oYkMSftV0NcTUMi3vjzVPvP0BMS2XxEXDgTEsluM8qDZG79yzArP fzovkE90c1HGLWf37KTImamCkrsr6ANQYfVJdBp3Oo2Kkk3og8DjS/A3m60XmGUOCT7/h453Vns vFw= X-Google-Smtp-Source: AGHT+IGZ3e/LBC9oFo92G9gFvFYL6g4CWsC0kkEIeD2dmJfNrUDCabnMPaFC52kKEkSHxzG2IanhUQ== X-Received: by 2002:a05:620a:258b:b0:7b6:e9be:97dc with SMTP id af79cd13be357-7c047ba498bmr301516785a.8.1738907123361; Thu, 06 Feb 2025 21:45:23 -0800 (PST) Received: from debian.debian ([2a09:bac5:79dd:25a5::3c0:2]) by smtp.gmail.com with ESMTPSA id af79cd13be357-7c041eb7f94sm147517385a.96.2025.02.06.21.45.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Feb 2025 21:45:22 -0800 (PST) Date: Thu, 6 Feb 2025 21:45:20 -0800 From: Yan Zhai To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Mykola Lysenko , Shuah Khan , Yan Zhai , Brian Vazquez , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-team@cloudflare.com, Hou Tao Subject: [PATCH v2 bpf 2/2] selftests: bpf: test batch lookup on array of maps with holes Message-ID: <6e710c8034800cb14e7db2d77b2081222bcb247e.1738905497.git.yan@cloudflare.com> References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Iterating through array of maps may encounter non existing keys. The batch operation should not fail on when this happens. Signed-off-by: Yan Zhai Acked-by: Hou Tao --- .../bpf/map_tests/map_in_map_batch_ops.c | 62 +++++++++++++------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/tools/testing/selftests/bpf/map_tests/map_in_map_batch_ops.c b= /tools/testing/selftests/bpf/map_tests/map_in_map_batch_ops.c index 66191ae9863c..79c3ccadb962 100644 --- a/tools/testing/selftests/bpf/map_tests/map_in_map_batch_ops.c +++ b/tools/testing/selftests/bpf/map_tests/map_in_map_batch_ops.c @@ -120,11 +120,12 @@ static void validate_fetch_results(int outer_map_fd, =20 static void fetch_and_validate(int outer_map_fd, struct bpf_map_batch_opts *opts, - __u32 batch_size, bool delete_entries) + __u32 batch_size, bool delete_entries, + bool has_holes) { - __u32 *fetched_keys, *fetched_values, total_fetched =3D 0; - __u32 batch_key =3D 0, fetch_count, step_size; - int err, max_entries =3D OUTER_MAP_ENTRIES; + int err, max_entries =3D OUTER_MAP_ENTRIES - !!has_holes; + __u32 *fetched_keys, *fetched_values, total_fetched =3D 0, i; + __u32 batch_key =3D 0, fetch_count, step_size =3D batch_size; __u32 value_size =3D sizeof(__u32); =20 /* Total entries needs to be fetched */ @@ -134,9 +135,8 @@ static void fetch_and_validate(int outer_map_fd, "Memory allocation failed for fetched_keys or fetched_values", "error=3D%s\n", strerror(errno)); =20 - for (step_size =3D batch_size; - step_size <=3D max_entries; - step_size +=3D batch_size) { + /* hash map may not always return full batch */ + for (i =3D 0; i < OUTER_MAP_ENTRIES; i++) { fetch_count =3D step_size; err =3D delete_entries ? bpf_map_lookup_and_delete_batch(outer_map_fd, @@ -155,6 +155,7 @@ static void fetch_and_validate(int outer_map_fd, if (err && errno =3D=3D ENOSPC) { /* Fetch again with higher batch size */ total_fetched =3D 0; + step_size +=3D batch_size; continue; } =20 @@ -184,18 +185,19 @@ static void fetch_and_validate(int outer_map_fd, } =20 static void _map_in_map_batch_ops(enum bpf_map_type outer_map_type, - enum bpf_map_type inner_map_type) + enum bpf_map_type inner_map_type, + bool has_holes) { + __u32 max_entries =3D OUTER_MAP_ENTRIES - !!has_holes; __u32 *outer_map_keys, *inner_map_fds; - __u32 max_entries =3D OUTER_MAP_ENTRIES; LIBBPF_OPTS(bpf_map_batch_opts, opts); __u32 value_size =3D sizeof(__u32); int batch_size[2] =3D {5, 10}; __u32 map_index, op_index; int outer_map_fd, ret; =20 - outer_map_keys =3D calloc(max_entries, value_size); - inner_map_fds =3D calloc(max_entries, value_size); + outer_map_keys =3D calloc(OUTER_MAP_ENTRIES, value_size); + inner_map_fds =3D calloc(OUTER_MAP_ENTRIES, value_size); CHECK((!outer_map_keys || !inner_map_fds), "Memory allocation failed for outer_map_keys or inner_map_fds", "error=3D%s\n", strerror(errno)); @@ -209,6 +211,24 @@ static void _map_in_map_batch_ops(enum bpf_map_type ou= ter_map_type, ((outer_map_type =3D=3D BPF_MAP_TYPE_ARRAY_OF_MAPS) ? 9 : 1000) - map_index; =20 + /* This condition is only meaningful for array of maps. + * + * max_entries =3D=3D OUTER_MAP_ENTRIES - 1 if it is true. Say + * max_entries is short for n, then outer_map_keys looks like: + * + * [n, n-1, ... 2, 1] + * + * We change it to + * + * [n, n-1, ... 2, 0] + * + * So it will leave key 1 as a hole. It will serve to test the + * correctness when batch on an array: a "non-exist" key might be + * actually allocated and returned from key iteration. + */ + if (has_holes) + outer_map_keys[max_entries - 1]--; + /* batch operation - map_update */ ret =3D bpf_map_update_batch(outer_map_fd, outer_map_keys, inner_map_fds, &max_entries, &opts); @@ -219,15 +239,17 @@ static void _map_in_map_batch_ops(enum bpf_map_type o= uter_map_type, /* batch operation - map_lookup */ for (op_index =3D 0; op_index < 2; ++op_index) fetch_and_validate(outer_map_fd, &opts, - batch_size[op_index], false); + batch_size[op_index], false, + has_holes); =20 /* batch operation - map_lookup_delete */ if (outer_map_type =3D=3D BPF_MAP_TYPE_HASH_OF_MAPS) fetch_and_validate(outer_map_fd, &opts, - max_entries, true /*delete*/); + max_entries, true /*delete*/, + has_holes); =20 /* close all map fds */ - for (map_index =3D 0; map_index < max_entries; map_index++) + for (map_index =3D 0; map_index < OUTER_MAP_ENTRIES; map_index++) close(inner_map_fds[map_index]); close(outer_map_fd); =20 @@ -237,16 +259,20 @@ static void _map_in_map_batch_ops(enum bpf_map_type o= uter_map_type, =20 void test_map_in_map_batch_ops_array(void) { - _map_in_map_batch_ops(BPF_MAP_TYPE_ARRAY_OF_MAPS, BPF_MAP_TYPE_ARRAY); + _map_in_map_batch_ops(BPF_MAP_TYPE_ARRAY_OF_MAPS, BPF_MAP_TYPE_ARRAY, fal= se); printf("%s:PASS with inner ARRAY map\n", __func__); - _map_in_map_batch_ops(BPF_MAP_TYPE_ARRAY_OF_MAPS, BPF_MAP_TYPE_HASH); + _map_in_map_batch_ops(BPF_MAP_TYPE_ARRAY_OF_MAPS, BPF_MAP_TYPE_HASH, fals= e); printf("%s:PASS with inner HASH map\n", __func__); + _map_in_map_batch_ops(BPF_MAP_TYPE_ARRAY_OF_MAPS, BPF_MAP_TYPE_ARRAY, tru= e); + printf("%s:PASS with inner ARRAY map with holes\n", __func__); + _map_in_map_batch_ops(BPF_MAP_TYPE_ARRAY_OF_MAPS, BPF_MAP_TYPE_HASH, true= ); + printf("%s:PASS with inner HASH map with holes\n", __func__); } =20 void test_map_in_map_batch_ops_hash(void) { - _map_in_map_batch_ops(BPF_MAP_TYPE_HASH_OF_MAPS, BPF_MAP_TYPE_ARRAY); + _map_in_map_batch_ops(BPF_MAP_TYPE_HASH_OF_MAPS, BPF_MAP_TYPE_ARRAY, fals= e); printf("%s:PASS with inner ARRAY map\n", __func__); - _map_in_map_batch_ops(BPF_MAP_TYPE_HASH_OF_MAPS, BPF_MAP_TYPE_HASH); + _map_in_map_batch_ops(BPF_MAP_TYPE_HASH_OF_MAPS, BPF_MAP_TYPE_HASH, false= ); printf("%s:PASS with inner HASH map\n", __func__); } --=20 2.39.5