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