Use the same test buffers as the traditional iterator and a new BPF map
to verify the test buffers can be found with the open coded dmabuf
iterator.
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
.../testing/selftests/bpf/bpf_experimental.h | 5 ++
.../selftests/bpf/prog_tests/dmabuf_iter.c | 52 +++++++++++++++----
.../testing/selftests/bpf/progs/dmabuf_iter.c | 38 ++++++++++++++
3 files changed, 86 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
index 6535c8ae3c46..5e512a1d09d1 100644
--- a/tools/testing/selftests/bpf/bpf_experimental.h
+++ b/tools/testing/selftests/bpf/bpf_experimental.h
@@ -591,4 +591,9 @@ extern int bpf_iter_kmem_cache_new(struct bpf_iter_kmem_cache *it) __weak __ksym
extern struct kmem_cache *bpf_iter_kmem_cache_next(struct bpf_iter_kmem_cache *it) __weak __ksym;
extern void bpf_iter_kmem_cache_destroy(struct bpf_iter_kmem_cache *it) __weak __ksym;
+struct bpf_iter_dmabuf;
+extern int bpf_iter_dmabuf_new(struct bpf_iter_dmabuf *it) __weak __ksym;
+extern struct dma_buf *bpf_iter_dmabuf_next(struct bpf_iter_dmabuf *it) __weak __ksym;
+extern void bpf_iter_dmabuf_destroy(struct bpf_iter_dmabuf *it) __weak __ksym;
+
#endif
diff --git a/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c b/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
index 35745f4ce0f8..c8230a080ef3 100644
--- a/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
+++ b/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
@@ -26,10 +26,11 @@ static int sysheap_dmabuf;
static const char sysheap_test_buffer_name[DMA_BUF_NAME_LEN] = "sysheap_test_buffer_for_iter";
static size_t sysheap_test_buffer_size;
-static int create_udmabuf(void)
+static int create_udmabuf(int map_fd)
{
struct udmabuf_create create;
int dev_udmabuf;
+ bool f = false;
udmabuf_test_buffer_size = 10 * getpagesize();
@@ -63,10 +64,10 @@ static int create_udmabuf(void)
if (!ASSERT_OK(ioctl(udmabuf, DMA_BUF_SET_NAME_B, udmabuf_test_buffer_name), "name"))
return 1;
- return 0;
+ return bpf_map_update_elem(map_fd, udmabuf_test_buffer_name, &f, BPF_ANY);
}
-static int create_sys_heap_dmabuf(void)
+static int create_sys_heap_dmabuf(int map_fd)
{
sysheap_test_buffer_size = 20 * getpagesize();
@@ -77,6 +78,7 @@ static int create_sys_heap_dmabuf(void)
.heap_flags = 0,
};
int heap_fd, ret;
+ bool f = false;
if (!ASSERT_LE(sizeof(sysheap_test_buffer_name), DMA_BUF_NAME_LEN, "NAMETOOLONG"))
return 1;
@@ -95,18 +97,18 @@ static int create_sys_heap_dmabuf(void)
if (!ASSERT_OK(ioctl(sysheap_dmabuf, DMA_BUF_SET_NAME_B, sysheap_test_buffer_name), "name"))
return 1;
- return 0;
+ return bpf_map_update_elem(map_fd, sysheap_test_buffer_name, &f, BPF_ANY);
}
-static int create_test_buffers(void)
+static int create_test_buffers(int map_fd)
{
int ret;
- ret = create_udmabuf();
+ ret = create_udmabuf(map_fd);
if (ret)
return ret;
- return create_sys_heap_dmabuf();
+ return create_sys_heap_dmabuf(map_fd);
}
static void destroy_test_buffers(void)
@@ -187,17 +189,46 @@ static void subtest_dmabuf_iter_check_default_iter(struct dmabuf_iter *skel)
close(iter_fd);
}
+static void subtest_dmabuf_iter_check_open_coded(struct dmabuf_iter *skel, int map_fd)
+{
+ LIBBPF_OPTS(bpf_test_run_opts, topts);
+ char key[DMA_BUF_NAME_LEN];
+ int err, fd;
+ bool found;
+
+ /* No need to attach it, just run it directly */
+ fd = bpf_program__fd(skel->progs.iter_dmabuf_for_each);
+
+ err = bpf_prog_test_run_opts(fd, &topts);
+ if (!ASSERT_OK(err, "test_run_opts err"))
+ return;
+ if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
+ return;
+
+ if (!ASSERT_OK(bpf_map_get_next_key(map_fd, NULL, key), "get next key"))
+ return;
+
+ do {
+ ASSERT_OK(bpf_map_lookup_elem(map_fd, key, &found), "lookup");
+ ASSERT_TRUE(found, "found test buffer");
+ } while (bpf_map_get_next_key(map_fd, key, key));
+}
+
void test_dmabuf_iter(void)
{
struct dmabuf_iter *skel = NULL;
+ int iter_fd, map_fd;
char buf[256];
- int iter_fd;
skel = dmabuf_iter__open_and_load();
if (!ASSERT_OK_PTR(skel, "dmabuf_iter__open_and_load"))
return;
- if (!ASSERT_OK(create_test_buffers(), "create_buffers"))
+ map_fd = bpf_map__fd(skel->maps.testbuf_hash);
+ if (!ASSERT_OK_FD(map_fd, "map_fd"))
+ goto destroy_skel;
+
+ if (!ASSERT_OK(create_test_buffers(map_fd), "create_buffers"))
goto destroy;
if (!ASSERT_OK(dmabuf_iter__attach(skel), "skel_attach"))
@@ -215,10 +246,13 @@ void test_dmabuf_iter(void)
if (test__start_subtest("default_iter"))
subtest_dmabuf_iter_check_default_iter(skel);
+ if (test__start_subtest("open_coded"))
+ subtest_dmabuf_iter_check_open_coded(skel, map_fd);
close(iter_fd);
destroy:
destroy_test_buffers();
+destroy_skel:
dmabuf_iter__destroy(skel);
}
diff --git a/tools/testing/selftests/bpf/progs/dmabuf_iter.c b/tools/testing/selftests/bpf/progs/dmabuf_iter.c
index d654b4f64cfa..cfdcf4b1c636 100644
--- a/tools/testing/selftests/bpf/progs/dmabuf_iter.c
+++ b/tools/testing/selftests/bpf/progs/dmabuf_iter.c
@@ -9,6 +9,13 @@
char _license[] SEC("license") = "GPL";
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(key_size, DMA_BUF_NAME_LEN);
+ __type(value, bool);
+ __uint(max_entries, 5);
+} testbuf_hash SEC(".maps");
+
/*
* Fields output by this iterator are delimited by newlines. Convert any
* newlines in user-provided printed strings to spaces.
@@ -51,3 +58,34 @@ int dmabuf_collector(struct bpf_iter__dmabuf *ctx)
BPF_SEQ_PRINTF(seq, "%lu\n%llu\n%s\n%s\n", inode, size, name, exporter);
return 0;
}
+
+SEC("syscall")
+int iter_dmabuf_for_each(const void *ctx)
+{
+ struct dma_buf *d;
+
+ bpf_for_each(dmabuf, d) {
+ char name[DMA_BUF_NAME_LEN];
+ const char *pname;
+ bool *found;
+
+ if (bpf_core_read(&pname, sizeof(pname), &d->name))
+ return 1;
+
+ /* Buffers are not required to be named */
+ if (!pname)
+ continue;
+
+ if (bpf_probe_read_kernel(name, sizeof(name), pname))
+ return 1;
+
+ found = bpf_map_lookup_elem(&testbuf_hash, name);
+ if (found) {
+ bool t = true;
+
+ bpf_map_update_elem(&testbuf_hash, name, &t, BPF_EXIST);
+ }
+ }
+
+ return 0;
+}
--
2.49.0.1015.ga840276032-goog
On Thu, May 8, 2025 at 11:21 AM T.J. Mercier <tjmercier@google.com> wrote:
>
> Use the same test buffers as the traditional iterator and a new BPF map
> to verify the test buffers can be found with the open coded dmabuf
> iterator.
The way we split 4/5 and 5/5 makes the code tricker to follow. I guess
the motivation is to back port default iter along to older kernels. But I
think we can still make the code cleaner.
>
> Signed-off-by: T.J. Mercier <tjmercier@google.com>
> ---
[...]
>
> -static int create_udmabuf(void)
> +static int create_udmabuf(int map_fd)
> {
> struct udmabuf_create create;
> int dev_udmabuf;
> + bool f = false;
>
> udmabuf_test_buffer_size = 10 * getpagesize();
>
> @@ -63,10 +64,10 @@ static int create_udmabuf(void)
> if (!ASSERT_OK(ioctl(udmabuf, DMA_BUF_SET_NAME_B, udmabuf_test_buffer_name), "name"))
> return 1;
>
> - return 0;
> + return bpf_map_update_elem(map_fd, udmabuf_test_buffer_name, &f, BPF_ANY);
We don't really need this bpf_map_update_elem() inside
create_udmabuf(), right?
> }
>
> -static int create_sys_heap_dmabuf(void)
> +static int create_sys_heap_dmabuf(int map_fd)
> {
> sysheap_test_buffer_size = 20 * getpagesize();
>
> @@ -77,6 +78,7 @@ static int create_sys_heap_dmabuf(void)
> .heap_flags = 0,
> };
> int heap_fd, ret;
> + bool f = false;
>
> if (!ASSERT_LE(sizeof(sysheap_test_buffer_name), DMA_BUF_NAME_LEN, "NAMETOOLONG"))
> return 1;
> @@ -95,18 +97,18 @@ static int create_sys_heap_dmabuf(void)
> if (!ASSERT_OK(ioctl(sysheap_dmabuf, DMA_BUF_SET_NAME_B, sysheap_test_buffer_name), "name"))
> return 1;
>
> - return 0;
> + return bpf_map_update_elem(map_fd, sysheap_test_buffer_name, &f, BPF_ANY);
Same for this bpf_map_update_elem(), we can call this directly from
create_test_buffers().
> }
>
> -static int create_test_buffers(void)
> +static int create_test_buffers(int map_fd)
> {
> int ret;
>
> - ret = create_udmabuf();
> + ret = create_udmabuf(map_fd);
> if (ret)
> return ret;
>
> - return create_sys_heap_dmabuf();
> + return create_sys_heap_dmabuf(map_fd);
Personally, I would prefer we just merge all the logic of
create_udmabuf() and create_sys_heap_dmabuf()
into create_test_buffers().
> }
>
[...]
> +
> void test_dmabuf_iter(void)
> {
> struct dmabuf_iter *skel = NULL;
> + int iter_fd, map_fd;
> char buf[256];
> - int iter_fd;
>
> skel = dmabuf_iter__open_and_load();
> if (!ASSERT_OK_PTR(skel, "dmabuf_iter__open_and_load"))
> return;
>
> - if (!ASSERT_OK(create_test_buffers(), "create_buffers"))
> + map_fd = bpf_map__fd(skel->maps.testbuf_hash);
> + if (!ASSERT_OK_FD(map_fd, "map_fd"))
> + goto destroy_skel;
> +
> + if (!ASSERT_OK(create_test_buffers(map_fd), "create_buffers"))
> goto destroy;
>
> if (!ASSERT_OK(dmabuf_iter__attach(skel), "skel_attach"))
> @@ -215,10 +246,13 @@ void test_dmabuf_iter(void)
>
> if (test__start_subtest("default_iter"))
> subtest_dmabuf_iter_check_default_iter(skel);
> + if (test__start_subtest("open_coded"))
> + subtest_dmabuf_iter_check_open_coded(skel, map_fd);
>
> close(iter_fd);
>
> destroy:
> destroy_test_buffers();
> +destroy_skel:
> dmabuf_iter__destroy(skel);
> }
[...]
On Fri, May 9, 2025 at 11:46 AM Song Liu <song@kernel.org> wrote:
>
> On Thu, May 8, 2025 at 11:21 AM T.J. Mercier <tjmercier@google.com> wrote:
> >
> > Use the same test buffers as the traditional iterator and a new BPF map
> > to verify the test buffers can be found with the open coded dmabuf
> > iterator.
>
> The way we split 4/5 and 5/5 makes the code tricker to follow. I guess
> the motivation is to back port default iter along to older kernels. But I
> think we can still make the code cleaner.
>
> >
> > Signed-off-by: T.J. Mercier <tjmercier@google.com>
> > ---
> [...]
>
> >
> > -static int create_udmabuf(void)
> > +static int create_udmabuf(int map_fd)
> > {
> > struct udmabuf_create create;
> > int dev_udmabuf;
> > + bool f = false;
> >
> > udmabuf_test_buffer_size = 10 * getpagesize();
> >
> > @@ -63,10 +64,10 @@ static int create_udmabuf(void)
> > if (!ASSERT_OK(ioctl(udmabuf, DMA_BUF_SET_NAME_B, udmabuf_test_buffer_name), "name"))
> > return 1;
> >
> > - return 0;
> > + return bpf_map_update_elem(map_fd, udmabuf_test_buffer_name, &f, BPF_ANY);
>
> We don't really need this bpf_map_update_elem() inside
> create_udmabuf(), right?
>
> > }
> >
> > -static int create_sys_heap_dmabuf(void)
> > +static int create_sys_heap_dmabuf(int map_fd)
> > {
> > sysheap_test_buffer_size = 20 * getpagesize();
> >
> > @@ -77,6 +78,7 @@ static int create_sys_heap_dmabuf(void)
> > .heap_flags = 0,
> > };
> > int heap_fd, ret;
> > + bool f = false;
> >
> > if (!ASSERT_LE(sizeof(sysheap_test_buffer_name), DMA_BUF_NAME_LEN, "NAMETOOLONG"))
> > return 1;
> > @@ -95,18 +97,18 @@ static int create_sys_heap_dmabuf(void)
> > if (!ASSERT_OK(ioctl(sysheap_dmabuf, DMA_BUF_SET_NAME_B, sysheap_test_buffer_name), "name"))
> > return 1;
> >
> > - return 0;
> > + return bpf_map_update_elem(map_fd, sysheap_test_buffer_name, &f, BPF_ANY);
>
> Same for this bpf_map_update_elem(), we can call this directly from
> create_test_buffers().
>
> > }
> >
> > -static int create_test_buffers(void)
> > +static int create_test_buffers(int map_fd)
> > {
> > int ret;
> >
> > - ret = create_udmabuf();
> > + ret = create_udmabuf(map_fd);
> > if (ret)
> > return ret;
> >
> > - return create_sys_heap_dmabuf();
> > + return create_sys_heap_dmabuf(map_fd);
>
> Personally, I would prefer we just merge all the logic of
> create_udmabuf() and create_sys_heap_dmabuf()
> into create_test_buffers().
That's a lot of different stuff to put in one place. How about
returning file descriptors from the buffer create functions while
having them clean up after themselves:
-static int memfd, udmabuf;
+static int udmabuf;
static const char udmabuf_test_buffer_name[DMA_BUF_NAME_LEN] =
"udmabuf_test_buffer_for_iter";
static size_t udmabuf_test_buffer_size;
static int sysheap_dmabuf;
static const char sysheap_test_buffer_name[DMA_BUF_NAME_LEN] =
"sysheap_test_buffer_for_iter";
static size_t sysheap_test_buffer_size;
-static int create_udmabuf(int map_fd)
+static int create_udmabuf(void)
{
struct udmabuf_create create;
- int dev_udmabuf;
- bool f = false;
+ int dev_udmabuf, memfd, udmabuf;
udmabuf_test_buffer_size = 10 * getpagesize();
if (!ASSERT_LE(sizeof(udmabuf_test_buffer_name),
DMA_BUF_NAME_LEN, "NAMETOOLONG"))
- return 1;
+ return -1;
memfd = memfd_create("memfd_test", MFD_ALLOW_SEALING);
if (!ASSERT_OK_FD(memfd, "memfd_create"))
- return 1;
+ return -1;
if (!ASSERT_OK(ftruncate(memfd, udmabuf_test_buffer_size), "ftruncate"))
- return 1;
+ goto close_memfd;
if (!ASSERT_OK(fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK), "seal"))
- return 1;
+ goto close_memfd;
dev_udmabuf = open("/dev/udmabuf", O_RDONLY);
if (!ASSERT_OK_FD(dev_udmabuf, "open udmabuf"))
- return 1;
+ goto close_memfd;
create.memfd = memfd;
create.flags = UDMABUF_FLAGS_CLOEXEC;
@@ -59,15 +58,21 @@ static int create_udmabuf(int map_fd)
udmabuf = ioctl(dev_udmabuf, UDMABUF_CREATE, &create);
close(dev_udmabuf);
if (!ASSERT_OK_FD(udmabuf, "udmabuf_create"))
- return 1;
+ goto close_memfd;
if (!ASSERT_OK(ioctl(udmabuf, DMA_BUF_SET_NAME_B,
udmabuf_test_buffer_name), "name"))
- return 1;
+ goto close_udmabuf;
+
+ return udmabuf;
- return bpf_map_update_elem(map_fd, udmabuf_test_buffer_name,
&f, BPF_ANY);
+close_udmabuf:
+ close(udmabuf);
+close_memfd:
+ close(memfd);
+ return -1;
}
-static int create_sys_heap_dmabuf(int map_fd)
+static int create_sys_heap_dmabuf(void)
{
sysheap_test_buffer_size = 20 * getpagesize();
@@ -78,43 +83,46 @@ static int create_sys_heap_dmabuf(int map_fd)
.heap_flags = 0,
};
int heap_fd, ret;
- bool f = false;
if (!ASSERT_LE(sizeof(sysheap_test_buffer_name),
DMA_BUF_NAME_LEN, "NAMETOOLONG"))
- return 1;
+ return -1;
heap_fd = open("/dev/dma_heap/system", O_RDONLY);
if (!ASSERT_OK_FD(heap_fd, "open dma heap"))
- return 1;
+ return -1;
ret = ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC, &data);
close(heap_fd);
if (!ASSERT_OK(ret, "syheap alloc"))
- return 1;
+ return -1;
- sysheap_dmabuf = data.fd;
+ if (!ASSERT_OK(ioctl(data.fd, DMA_BUF_SET_NAME_B,
sysheap_test_buffer_name), "name"))
+ goto close_sysheap_dmabuf;
- if (!ASSERT_OK(ioctl(sysheap_dmabuf, DMA_BUF_SET_NAME_B,
sysheap_test_buffer_name), "name"))
- return 1;
+ return data.fd;
- return bpf_map_update_elem(map_fd, sysheap_test_buffer_name,
&f, BPF_ANY);
+close_sysheap_dmabuf:
+ close(data.fd);
+ return -1;
}
static int create_test_buffers(int map_fd)
{
- int ret;
+ bool f = false;
+
+ udmabuf = create_udmabuf();
+ sysheap_dmabuf = create_sys_heap_dmabuf();
- ret = create_udmabuf(map_fd);
- if (ret)
- return ret;
+ if (udmabuf < 0 || sysheap_dmabuf < 0)
+ return -1;
- return create_sys_heap_dmabuf(map_fd);
+ return bpf_map_update_elem(map_fd, udmabuf_test_buffer_name,
&f, BPF_ANY) ||
+ bpf_map_update_elem(map_fd, sysheap_test_buffer_name,
&f, BPF_ANY);
}
static void destroy_test_buffers(void)
{
close(udmabuf);
- close(memfd);
close(sysheap_dmabuf);
}
On Fri, May 9, 2025 at 2:43 PM T.J. Mercier <tjmercier@google.com> wrote:
>
[...]
> >
> > Personally, I would prefer we just merge all the logic of
> > create_udmabuf() and create_sys_heap_dmabuf()
> > into create_test_buffers().
>
> That's a lot of different stuff to put in one place. How about
> returning file descriptors from the buffer create functions while
> having them clean up after themselves:
I do like this version better. Some nitpicks though.
>
> -static int memfd, udmabuf;
> +static int udmabuf;
About this, and ...
> static const char udmabuf_test_buffer_name[DMA_BUF_NAME_LEN] =
> "udmabuf_test_buffer_for_iter";
> static size_t udmabuf_test_buffer_size;
> static int sysheap_dmabuf;
> static const char sysheap_test_buffer_name[DMA_BUF_NAME_LEN] =
> "sysheap_test_buffer_for_iter";
> static size_t sysheap_test_buffer_size;
>
> -static int create_udmabuf(int map_fd)
> +static int create_udmabuf(void)
> {
> struct udmabuf_create create;
> - int dev_udmabuf;
> - bool f = false;
> + int dev_udmabuf, memfd, udmabuf;
.. here.
It is not ideal to have a global udmabuf and a local udmabuf.
If we want the global version, let's rename the local one.
[...]
>
> static int create_test_buffers(int map_fd)
> {
> - int ret;
> + bool f = false;
> +
> + udmabuf = create_udmabuf();
> + sysheap_dmabuf = create_sys_heap_dmabuf();
>
> - ret = create_udmabuf(map_fd);
> - if (ret)
> - return ret;
> + if (udmabuf < 0 || sysheap_dmabuf < 0)
> + return -1;
We also need destroy_test_buffers() on the error path here,
or at the caller.
>
> - return create_sys_heap_dmabuf(map_fd);
> + return bpf_map_update_elem(map_fd, udmabuf_test_buffer_name,
> &f, BPF_ANY) ||
> + bpf_map_update_elem(map_fd, sysheap_test_buffer_name,
> &f, BPF_ANY);
> }
>
> static void destroy_test_buffers(void)
> {
> close(udmabuf);
> - close(memfd);
> close(sysheap_dmabuf);
For the two global fds, let's reset them to -1 right after close().
Thanks,
Song
On Fri, May 9, 2025 at 2:58 PM Song Liu <song@kernel.org> wrote:
>
> On Fri, May 9, 2025 at 2:43 PM T.J. Mercier <tjmercier@google.com> wrote:
> >
> [...]
> > >
> > > Personally, I would prefer we just merge all the logic of
> > > create_udmabuf() and create_sys_heap_dmabuf()
> > > into create_test_buffers().
> >
> > That's a lot of different stuff to put in one place. How about
> > returning file descriptors from the buffer create functions while
> > having them clean up after themselves:
>
> I do like this version better. Some nitpicks though.
>
> >
> > -static int memfd, udmabuf;
> > +static int udmabuf;
>
> About this, and ...
>
> > static const char udmabuf_test_buffer_name[DMA_BUF_NAME_LEN] =
> > "udmabuf_test_buffer_for_iter";
> > static size_t udmabuf_test_buffer_size;
> > static int sysheap_dmabuf;
> > static const char sysheap_test_buffer_name[DMA_BUF_NAME_LEN] =
> > "sysheap_test_buffer_for_iter";
> > static size_t sysheap_test_buffer_size;
> >
> > -static int create_udmabuf(int map_fd)
> > +static int create_udmabuf(void)
> > {
> > struct udmabuf_create create;
> > - int dev_udmabuf;
> > - bool f = false;
> > + int dev_udmabuf, memfd, udmabuf;
> .. here.
>
> It is not ideal to have a global udmabuf and a local udmabuf.
> If we want the global version, let's rename the local one.
Ok let me change up the name of the aliasing variable to local_udmabuf.
> [...]
>
> >
> > static int create_test_buffers(int map_fd)
> > {
> > - int ret;
> > + bool f = false;
> > +
> > + udmabuf = create_udmabuf();
> > + sysheap_dmabuf = create_sys_heap_dmabuf();
> >
> > - ret = create_udmabuf(map_fd);
> > - if (ret)
> > - return ret;
> > + if (udmabuf < 0 || sysheap_dmabuf < 0)
> > + return -1;
>
> We also need destroy_test_buffers() on the error path here,
> or at the caller.
The caller does currently check to decide if it should bother running
the tests or not, and calls destroy_test_buffers() if not.
> > - return create_sys_heap_dmabuf(map_fd);
> > + return bpf_map_update_elem(map_fd, udmabuf_test_buffer_name,
> > &f, BPF_ANY) ||
> > + bpf_map_update_elem(map_fd, sysheap_test_buffer_name,
> > &f, BPF_ANY);
> > }
> >
> > static void destroy_test_buffers(void)
> > {
> > close(udmabuf);
> > - close(memfd);
> > close(sysheap_dmabuf);
>
> For the two global fds, let's reset them to -1 right after close().
>
> Thanks,
> Song
Will do, thanks.
© 2016 - 2026 Red Hat, Inc.