blob: ea5b568c00478da001f77ed9865f9a8fdd153d68 [file] [log] [blame]
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
// Copyright (c) 2020 Anton Protopopov
#ifndef __MAPS_BPF_H
#define __MAPS_BPF_H
#include <bpf/bpf_helpers.h>
#include <asm-generic/errno.h>
static __always_inline void *
bpf_map_lookup_or_try_init(void *map, const void *key, const void *init)
{
void *val;
/* bpf helper functions like bpf_map_update_elem() below normally return
* long, but using int instead of long to store the result is a workaround
* to avoid incorrectly evaluating err in cases where the following criteria
* is met:
* the architecture is 64-bit
* the helper function return type is long
* the helper function returns the value of a call to a bpf_map_ops func
* the bpf_map_ops function return type is int
* the compiler inlines the helper function
* the compiler does not sign extend the result of the bpf_map_ops func
*
* if this criteria is met, at best an error can only be checked as zero or
* non-zero. it will not be possible to check for a negative value or a
* specific error value. this is because the sign bit would have been stuck
* at the 32nd bit of a 64-bit long int.
*/
int err;
val = bpf_map_lookup_elem(map, key);
if (val)
return val;
err = bpf_map_update_elem(map, key, init, BPF_NOEXIST);
if (err && err != -EEXIST)
return 0;
return bpf_map_lookup_elem(map, key);
}
#endif /* __MAPS_BPF_H */