Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/tools/testing/selftests/bpf/prog_tests/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  dmabuf_iter.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2025 Google */

#include <test_progs.h>
#include <bpf/libbpf.h>
#include <bpf/btf.h>
#include "dmabuf_iter.skel.h"

#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>

#include <linux/dma-buf.h>
#include <linux/dma-heap.h>
#include <linux/udmabuf.h>

static int udmabuf = -1;
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 = -1;
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)
{
 struct udmabuf_create create;
 int dev_udmabuf, memfd, local_udmabuf;

 udmabuf_test_buffer_size = 10 * getpagesize();

 if (!ASSERT_LE(sizeof(udmabuf_test_buffer_name), DMA_BUF_NAME_LEN, "NAMETOOLONG"))
  return -1;

 memfd = memfd_create("memfd_test", MFD_ALLOW_SEALING);
 if (!ASSERT_OK_FD(memfd, "memfd_create"))
  return -1;

 if (!ASSERT_OK(ftruncate(memfd, udmabuf_test_buffer_size), "ftruncate"))
  goto close_memfd;

 if (!ASSERT_OK(fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK), "seal"))
  goto close_memfd;

 dev_udmabuf = open("/dev/udmabuf", O_RDONLY);
 if (!ASSERT_OK_FD(dev_udmabuf, "open udmabuf"))
  goto close_memfd;

 memset(&create, 0, sizeof(create));
 create.memfd = memfd;
 create.flags = UDMABUF_FLAGS_CLOEXEC;
 create.offset = 0;
 create.size = udmabuf_test_buffer_size;

 local_udmabuf = ioctl(dev_udmabuf, UDMABUF_CREATE, &create);
 close(dev_udmabuf);
 if (!ASSERT_OK_FD(local_udmabuf, "udmabuf_create"))
  goto close_memfd;

 if (!ASSERT_OK(ioctl(local_udmabuf, DMA_BUF_SET_NAME_B, udmabuf_test_buffer_name), "name"))
  goto close_udmabuf;

 return local_udmabuf;

close_udmabuf:
 close(local_udmabuf);
close_memfd:
 close(memfd);
 return -1;
}

static int create_sys_heap_dmabuf(void)
{
 sysheap_test_buffer_size = 20 * getpagesize();

 struct dma_heap_allocation_data data = {
  .len = sysheap_test_buffer_size,
  .fd = 0,
  .fd_flags = O_RDWR | O_CLOEXEC,
  .heap_flags = 0,
 };
 int heap_fd, ret;

 if (!ASSERT_LE(sizeof(sysheap_test_buffer_name), DMA_BUF_NAME_LEN, "NAMETOOLONG"))
  return -1;

 heap_fd = open("/dev/dma_heap/system", O_RDONLY);
 if (!ASSERT_OK_FD(heap_fd, "open dma heap"))
  return -1;

 ret = ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC, &data);
 close(heap_fd);
 if (!ASSERT_OK(ret, "syheap alloc"))
  return -1;

 if (!ASSERT_OK(ioctl(data.fd, DMA_BUF_SET_NAME_B, sysheap_test_buffer_name), "name"))
  goto close_sysheap_dmabuf;

 return data.fd;

close_sysheap_dmabuf:
 close(data.fd);
 return -1;
}

static int create_test_buffers(void)
{
 udmabuf = create_udmabuf();
 sysheap_dmabuf = create_sys_heap_dmabuf();

 if (udmabuf < 0 || sysheap_dmabuf < 0)
  return -1;

 return 0;
}

static void destroy_test_buffers(void)
{
 close(udmabuf);
 udmabuf = -1;

 close(sysheap_dmabuf);
 sysheap_dmabuf = -1;
}

enum Fields { INODE, SIZE, NAME, EXPORTER, FIELD_COUNT };
struct DmabufInfo {
 unsigned long inode;
 unsigned long size;
 char name[DMA_BUF_NAME_LEN];
 char exporter[32];
};

static bool check_dmabuf_info(const struct DmabufInfo *bufinfo,
         unsigned long size,
         const char *name, const char *exporter)
{
 return size == bufinfo->size &&
        !strcmp(name, bufinfo->name) &&
        !strcmp(exporter, bufinfo->exporter);
}

static void subtest_dmabuf_iter_check_no_infinite_reads(struct dmabuf_iter *skel)
{
 int iter_fd;
 char buf[256];

 iter_fd = bpf_iter_create(bpf_link__fd(skel->links.dmabuf_collector));
 if (!ASSERT_OK_FD(iter_fd, "iter_create"))
  return;

 while (read(iter_fd, buf, sizeof(buf)) > 0)
  ; /* Read out all contents */

 /* Next reads should return 0 */
 ASSERT_EQ(read(iter_fd, buf, sizeof(buf)), 0, "read");

 close(iter_fd);
}

static void subtest_dmabuf_iter_check_default_iter(struct dmabuf_iter *skel)
{
 bool found_test_sysheap_dmabuf = false;
 bool found_test_udmabuf = false;
 struct DmabufInfo bufinfo;
 size_t linesize = 0;
 char *line = NULL;
 FILE *iter_file;
 int iter_fd, f = INODE;

 iter_fd = bpf_iter_create(bpf_link__fd(skel->links.dmabuf_collector));
 if (!ASSERT_OK_FD(iter_fd, "iter_create"))
  return;

 iter_file = fdopen(iter_fd, "r");
 if (!ASSERT_OK_PTR(iter_file, "fdopen"))
  goto close_iter_fd;

 while (getline(&line, &linesize, iter_file) != -1) {
  if (f % FIELD_COUNT == INODE) {
   ASSERT_EQ(sscanf(line, "%ld", &bufinfo.inode), 1,
      "read inode");
  } else if (f % FIELD_COUNT == SIZE) {
   ASSERT_EQ(sscanf(line, "%ld", &bufinfo.size), 1,
      "read size");
  } else if (f % FIELD_COUNT == NAME) {
   ASSERT_EQ(sscanf(line, "%s", bufinfo.name), 1,
      "read name");
  } else if (f % FIELD_COUNT == EXPORTER) {
   ASSERT_EQ(sscanf(line, "%31s", bufinfo.exporter), 1,
      "read exporter");

   if (check_dmabuf_info(&bufinfo,
           sysheap_test_buffer_size,
           sysheap_test_buffer_name,
           "system"))
    found_test_sysheap_dmabuf = true;
   else if (check_dmabuf_info(&bufinfo,
         udmabuf_test_buffer_size,
         udmabuf_test_buffer_name,
         "udmabuf"))
    found_test_udmabuf = true;
  }
  ++f;
 }

 ASSERT_EQ(f % FIELD_COUNT, INODE, "number of fields");

 ASSERT_TRUE(found_test_sysheap_dmabuf, "found_test_sysheap_dmabuf");
 ASSERT_TRUE(found_test_udmabuf, "found_test_udmabuf");

 free(line);
 fclose(iter_file);
close_iter_fd:
 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 map_fd;
 const bool f = false;

 skel = dmabuf_iter__open_and_load();
 if (!ASSERT_OK_PTR(skel, "dmabuf_iter__open_and_load"))
  return;

 map_fd = bpf_map__fd(skel->maps.testbuf_hash);
 if (!ASSERT_OK_FD(map_fd, "map_fd"))
  goto destroy_skel;

 if (!ASSERT_OK(bpf_map_update_elem(map_fd, udmabuf_test_buffer_name, &f, BPF_ANY),
         "insert udmabuf"))
  goto destroy_skel;
 if (!ASSERT_OK(bpf_map_update_elem(map_fd, sysheap_test_buffer_name, &f, BPF_ANY),
         "insert sysheap buffer"))
  goto destroy_skel;

 if (!ASSERT_OK(create_test_buffers(), "create_test_buffers"))
  goto destroy;

 if (!ASSERT_OK(dmabuf_iter__attach(skel), "skel_attach"))
  goto destroy;

 if (test__start_subtest("no_infinite_reads"))
  subtest_dmabuf_iter_check_no_infinite_reads(skel);
 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);

destroy:
 destroy_test_buffers();
destroy_skel:
 dmabuf_iter__destroy(skel);
}

Messung V0.5
C=91 H=93 G=91

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.