linux/tools/testing/selftests/bpf/prog_tests/pinning.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#include <sys/types.h>
   4#include <sys/stat.h>
   5#include <unistd.h>
   6#include <test_progs.h>
   7
   8__u32 get_map_id(struct bpf_object *obj, const char *name)
   9{
  10        struct bpf_map_info map_info = {};
  11        __u32 map_info_len, duration = 0;
  12        struct bpf_map *map;
  13        int err;
  14
  15        map_info_len = sizeof(map_info);
  16
  17        map = bpf_object__find_map_by_name(obj, name);
  18        if (CHECK(!map, "find map", "NULL map"))
  19                return 0;
  20
  21        err = bpf_obj_get_info_by_fd(bpf_map__fd(map),
  22                                     &map_info, &map_info_len);
  23        CHECK(err, "get map info", "err %d errno %d", err, errno);
  24        return map_info.id;
  25}
  26
  27void test_pinning(void)
  28{
  29        const char *file_invalid = "./test_pinning_invalid.o";
  30        const char *custpinpath = "/sys/fs/bpf/custom/pinmap";
  31        const char *nopinpath = "/sys/fs/bpf/nopinmap";
  32        const char *nopinpath2 = "/sys/fs/bpf/nopinmap2";
  33        const char *custpath = "/sys/fs/bpf/custom";
  34        const char *pinpath = "/sys/fs/bpf/pinmap";
  35        const char *file = "./test_pinning.o";
  36        __u32 map_id, map_id2, duration = 0;
  37        struct stat statbuf = {};
  38        struct bpf_object *obj;
  39        struct bpf_map *map;
  40        int err, map_fd;
  41        DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts,
  42                .pin_root_path = custpath,
  43        );
  44
  45        /* check that opening fails with invalid pinning value in map def */
  46        obj = bpf_object__open_file(file_invalid, NULL);
  47        err = libbpf_get_error(obj);
  48        if (CHECK(err != -EINVAL, "invalid open", "err %d errno %d\n", err, errno)) {
  49                obj = NULL;
  50                goto out;
  51        }
  52
  53        /* open the valid object file  */
  54        obj = bpf_object__open_file(file, NULL);
  55        err = libbpf_get_error(obj);
  56        if (CHECK(err, "default open", "err %d errno %d\n", err, errno)) {
  57                obj = NULL;
  58                goto out;
  59        }
  60
  61        err = bpf_object__load(obj);
  62        if (CHECK(err, "default load", "err %d errno %d\n", err, errno))
  63                goto out;
  64
  65        /* check that pinmap was pinned */
  66        err = stat(pinpath, &statbuf);
  67        if (CHECK(err, "stat pinpath", "err %d errno %d\n", err, errno))
  68                goto out;
  69
  70        /* check that nopinmap was *not* pinned */
  71        err = stat(nopinpath, &statbuf);
  72        if (CHECK(!err || errno != ENOENT, "stat nopinpath",
  73                  "err %d errno %d\n", err, errno))
  74                goto out;
  75
  76        /* check that nopinmap2 was *not* pinned */
  77        err = stat(nopinpath2, &statbuf);
  78        if (CHECK(!err || errno != ENOENT, "stat nopinpath2",
  79                  "err %d errno %d\n", err, errno))
  80                goto out;
  81
  82        map_id = get_map_id(obj, "pinmap");
  83        if (!map_id)
  84                goto out;
  85
  86        bpf_object__close(obj);
  87
  88        obj = bpf_object__open_file(file, NULL);
  89        if (CHECK_FAIL(libbpf_get_error(obj))) {
  90                obj = NULL;
  91                goto out;
  92        }
  93
  94        err = bpf_object__load(obj);
  95        if (CHECK(err, "default load", "err %d errno %d\n", err, errno))
  96                goto out;
  97
  98        /* check that same map ID was reused for second load */
  99        map_id2 = get_map_id(obj, "pinmap");
 100        if (CHECK(map_id != map_id2, "check reuse",
 101                  "err %d errno %d id %d id2 %d\n", err, errno, map_id, map_id2))
 102                goto out;
 103
 104        /* should be no-op to re-pin same map */
 105        map = bpf_object__find_map_by_name(obj, "pinmap");
 106        if (CHECK(!map, "find map", "NULL map"))
 107                goto out;
 108
 109        err = bpf_map__pin(map, NULL);
 110        if (CHECK(err, "re-pin map", "err %d errno %d\n", err, errno))
 111                goto out;
 112
 113        /* but error to pin at different location */
 114        err = bpf_map__pin(map, "/sys/fs/bpf/other");
 115        if (CHECK(!err, "pin map different", "err %d errno %d\n", err, errno))
 116                goto out;
 117
 118        /* unpin maps with a pin_path set */
 119        err = bpf_object__unpin_maps(obj, NULL);
 120        if (CHECK(err, "unpin maps", "err %d errno %d\n", err, errno))
 121                goto out;
 122
 123        /* and re-pin them... */
 124        err = bpf_object__pin_maps(obj, NULL);
 125        if (CHECK(err, "pin maps", "err %d errno %d\n", err, errno))
 126                goto out;
 127
 128        /* get pinning path */
 129        if (!ASSERT_STREQ(bpf_map__pin_path(map), pinpath, "get pin path"))
 130                goto out;
 131
 132        /* set pinning path of other map and re-pin all */
 133        map = bpf_object__find_map_by_name(obj, "nopinmap");
 134        if (CHECK(!map, "find map", "NULL map"))
 135                goto out;
 136
 137        err = bpf_map__set_pin_path(map, custpinpath);
 138        if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno))
 139                goto out;
 140
 141        /* get pinning path after set */
 142        if (!ASSERT_STREQ(bpf_map__pin_path(map), custpinpath,
 143                          "get pin path after set"))
 144                goto out;
 145
 146        /* should only pin the one unpinned map */
 147        err = bpf_object__pin_maps(obj, NULL);
 148        if (CHECK(err, "pin maps", "err %d errno %d\n", err, errno))
 149                goto out;
 150
 151        /* check that nopinmap was pinned at the custom path */
 152        err = stat(custpinpath, &statbuf);
 153        if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno))
 154                goto out;
 155
 156        /* remove the custom pin path to re-test it with auto-pinning below */
 157        err = unlink(custpinpath);
 158        if (CHECK(err, "unlink custpinpath", "err %d errno %d\n", err, errno))
 159                goto out;
 160
 161        err = rmdir(custpath);
 162        if (CHECK(err, "rmdir custpindir", "err %d errno %d\n", err, errno))
 163                goto out;
 164
 165        bpf_object__close(obj);
 166
 167        /* open the valid object file again */
 168        obj = bpf_object__open_file(file, NULL);
 169        err = libbpf_get_error(obj);
 170        if (CHECK(err, "default open", "err %d errno %d\n", err, errno)) {
 171                obj = NULL;
 172                goto out;
 173        }
 174
 175        /* set pin paths so that nopinmap2 will attempt to reuse the map at
 176         * pinpath (which will fail), but not before pinmap has already been
 177         * reused
 178         */
 179        bpf_object__for_each_map(map, obj) {
 180                if (!strcmp(bpf_map__name(map), "nopinmap"))
 181                        err = bpf_map__set_pin_path(map, nopinpath2);
 182                else if (!strcmp(bpf_map__name(map), "nopinmap2"))
 183                        err = bpf_map__set_pin_path(map, pinpath);
 184                else
 185                        continue;
 186
 187                if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno))
 188                        goto out;
 189        }
 190
 191        /* should fail because of map parameter mismatch */
 192        err = bpf_object__load(obj);
 193        if (CHECK(err != -EINVAL, "param mismatch load", "err %d errno %d\n", err, errno))
 194                goto out;
 195
 196        /* nopinmap2 should have been pinned and cleaned up again */
 197        err = stat(nopinpath2, &statbuf);
 198        if (CHECK(!err || errno != ENOENT, "stat nopinpath2",
 199                  "err %d errno %d\n", err, errno))
 200                goto out;
 201
 202        /* pinmap should still be there */
 203        err = stat(pinpath, &statbuf);
 204        if (CHECK(err, "stat pinpath", "err %d errno %d\n", err, errno))
 205                goto out;
 206
 207        bpf_object__close(obj);
 208
 209        /* test auto-pinning at custom path with open opt */
 210        obj = bpf_object__open_file(file, &opts);
 211        if (CHECK_FAIL(libbpf_get_error(obj))) {
 212                obj = NULL;
 213                goto out;
 214        }
 215
 216        err = bpf_object__load(obj);
 217        if (CHECK(err, "custom load", "err %d errno %d\n", err, errno))
 218                goto out;
 219
 220        /* check that pinmap was pinned at the custom path */
 221        err = stat(custpinpath, &statbuf);
 222        if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno))
 223                goto out;
 224
 225        /* remove the custom pin path to re-test it with reuse fd below */
 226        err = unlink(custpinpath);
 227        if (CHECK(err, "unlink custpinpath", "err %d errno %d\n", err, errno))
 228                goto out;
 229
 230        err = rmdir(custpath);
 231        if (CHECK(err, "rmdir custpindir", "err %d errno %d\n", err, errno))
 232                goto out;
 233
 234        bpf_object__close(obj);
 235
 236        /* test pinning at custom path with reuse fd */
 237        obj = bpf_object__open_file(file, NULL);
 238        err = libbpf_get_error(obj);
 239        if (CHECK(err, "default open", "err %d errno %d\n", err, errno)) {
 240                obj = NULL;
 241                goto out;
 242        }
 243
 244        map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(__u32),
 245                                sizeof(__u64), 1, 0);
 246        if (CHECK(map_fd < 0, "create pinmap manually", "fd %d\n", map_fd))
 247                goto out;
 248
 249        map = bpf_object__find_map_by_name(obj, "pinmap");
 250        if (CHECK(!map, "find map", "NULL map"))
 251                goto close_map_fd;
 252
 253        err = bpf_map__reuse_fd(map, map_fd);
 254        if (CHECK(err, "reuse pinmap fd", "err %d errno %d\n", err, errno))
 255                goto close_map_fd;
 256
 257        err = bpf_map__set_pin_path(map, custpinpath);
 258        if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno))
 259                goto close_map_fd;
 260
 261        err = bpf_object__load(obj);
 262        if (CHECK(err, "custom load", "err %d errno %d\n", err, errno))
 263                goto close_map_fd;
 264
 265        /* check that pinmap was pinned at the custom path */
 266        err = stat(custpinpath, &statbuf);
 267        if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno))
 268                goto close_map_fd;
 269
 270close_map_fd:
 271        close(map_fd);
 272out:
 273        unlink(pinpath);
 274        unlink(nopinpath);
 275        unlink(nopinpath2);
 276        unlink(custpinpath);
 277        rmdir(custpath);
 278        if (obj)
 279                bpf_object__close(obj);
 280}
 281