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        /* set pinning path of other map and re-pin all */
 129        map = bpf_object__find_map_by_name(obj, "nopinmap");
 130        if (CHECK(!map, "find map", "NULL map"))
 131                goto out;
 132
 133        err = bpf_map__set_pin_path(map, custpinpath);
 134        if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno))
 135                goto out;
 136
 137        /* should only pin the one unpinned map */
 138        err = bpf_object__pin_maps(obj, NULL);
 139        if (CHECK(err, "pin maps", "err %d errno %d\n", err, errno))
 140                goto out;
 141
 142        /* check that nopinmap was pinned at the custom path */
 143        err = stat(custpinpath, &statbuf);
 144        if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno))
 145                goto out;
 146
 147        /* remove the custom pin path to re-test it with auto-pinning below */
 148        err = unlink(custpinpath);
 149        if (CHECK(err, "unlink custpinpath", "err %d errno %d\n", err, errno))
 150                goto out;
 151
 152        err = rmdir(custpath);
 153        if (CHECK(err, "rmdir custpindir", "err %d errno %d\n", err, errno))
 154                goto out;
 155
 156        bpf_object__close(obj);
 157
 158        /* open the valid object file again */
 159        obj = bpf_object__open_file(file, NULL);
 160        err = libbpf_get_error(obj);
 161        if (CHECK(err, "default open", "err %d errno %d\n", err, errno)) {
 162                obj = NULL;
 163                goto out;
 164        }
 165
 166        /* set pin paths so that nopinmap2 will attempt to reuse the map at
 167         * pinpath (which will fail), but not before pinmap has already been
 168         * reused
 169         */
 170        bpf_object__for_each_map(map, obj) {
 171                if (!strcmp(bpf_map__name(map), "nopinmap"))
 172                        err = bpf_map__set_pin_path(map, nopinpath2);
 173                else if (!strcmp(bpf_map__name(map), "nopinmap2"))
 174                        err = bpf_map__set_pin_path(map, pinpath);
 175                else
 176                        continue;
 177
 178                if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno))
 179                        goto out;
 180        }
 181
 182        /* should fail because of map parameter mismatch */
 183        err = bpf_object__load(obj);
 184        if (CHECK(err != -EINVAL, "param mismatch load", "err %d errno %d\n", err, errno))
 185                goto out;
 186
 187        /* nopinmap2 should have been pinned and cleaned up again */
 188        err = stat(nopinpath2, &statbuf);
 189        if (CHECK(!err || errno != ENOENT, "stat nopinpath2",
 190                  "err %d errno %d\n", err, errno))
 191                goto out;
 192
 193        /* pinmap should still be there */
 194        err = stat(pinpath, &statbuf);
 195        if (CHECK(err, "stat pinpath", "err %d errno %d\n", err, errno))
 196                goto out;
 197
 198        bpf_object__close(obj);
 199
 200        /* test auto-pinning at custom path with open opt */
 201        obj = bpf_object__open_file(file, &opts);
 202        if (CHECK_FAIL(libbpf_get_error(obj))) {
 203                obj = NULL;
 204                goto out;
 205        }
 206
 207        err = bpf_object__load(obj);
 208        if (CHECK(err, "custom load", "err %d errno %d\n", err, errno))
 209                goto out;
 210
 211        /* check that pinmap was pinned at the custom path */
 212        err = stat(custpinpath, &statbuf);
 213        if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno))
 214                goto out;
 215
 216        /* remove the custom pin path to re-test it with reuse fd below */
 217        err = unlink(custpinpath);
 218        if (CHECK(err, "unlink custpinpath", "err %d errno %d\n", err, errno))
 219                goto out;
 220
 221        err = rmdir(custpath);
 222        if (CHECK(err, "rmdir custpindir", "err %d errno %d\n", err, errno))
 223                goto out;
 224
 225        bpf_object__close(obj);
 226
 227        /* test pinning at custom path with reuse fd */
 228        obj = bpf_object__open_file(file, NULL);
 229        err = libbpf_get_error(obj);
 230        if (CHECK(err, "default open", "err %d errno %d\n", err, errno)) {
 231                obj = NULL;
 232                goto out;
 233        }
 234
 235        map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(__u32),
 236                                sizeof(__u64), 1, 0);
 237        if (CHECK(map_fd < 0, "create pinmap manually", "fd %d\n", map_fd))
 238                goto out;
 239
 240        map = bpf_object__find_map_by_name(obj, "pinmap");
 241        if (CHECK(!map, "find map", "NULL map"))
 242                goto close_map_fd;
 243
 244        err = bpf_map__reuse_fd(map, map_fd);
 245        if (CHECK(err, "reuse pinmap fd", "err %d errno %d\n", err, errno))
 246                goto close_map_fd;
 247
 248        err = bpf_map__set_pin_path(map, custpinpath);
 249        if (CHECK(err, "set pin path", "err %d errno %d\n", err, errno))
 250                goto close_map_fd;
 251
 252        err = bpf_object__load(obj);
 253        if (CHECK(err, "custom load", "err %d errno %d\n", err, errno))
 254                goto close_map_fd;
 255
 256        /* check that pinmap was pinned at the custom path */
 257        err = stat(custpinpath, &statbuf);
 258        if (CHECK(err, "stat custpinpath", "err %d errno %d\n", err, errno))
 259                goto close_map_fd;
 260
 261close_map_fd:
 262        close(map_fd);
 263out:
 264        unlink(pinpath);
 265        unlink(nopinpath);
 266        unlink(nopinpath2);
 267        unlink(custpinpath);
 268        rmdir(custpath);
 269        if (obj)
 270                bpf_object__close(obj);
 271}
 272