drv_cgroup exercises both valid and invalid usage of the i915 cgroup parameter ioctl. Signed-off-by: Matt Roper <matthew.d.roper@xxxxxxxxx> --- tests/Makefile.sources | 1 + tests/drv_cgroup.c | 236 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 tests/drv_cgroup.c diff --git a/tests/Makefile.sources b/tests/Makefile.sources index 4a81ac4a..acba3f98 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -37,6 +37,7 @@ TESTS_progs = \ drm_vma_limiter_cached \ drm_vma_limiter_cpu \ drm_vma_limiter_gtt \ + drv_cgroup \ drv_getparams_basic \ drv_hangman \ drv_missed_irq \ diff --git a/tests/drv_cgroup.c b/tests/drv_cgroup.c new file mode 100644 index 00000000..6cc49539 --- /dev/null +++ b/tests/drv_cgroup.c @@ -0,0 +1,236 @@ +/* + * Copyright © 2018 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include "igt.h" +#include "igt_debugfs.h" +#include "igt_aux.h" +#include "igt_kmod.h" +#include "igt_sysfs.h" +#include "igt_core.h" + +#include <dirent.h> +#include <fcntl.h> +#include <libgen.h> +#include <signal.h> +#include <stdio.h> +#include <linux/limits.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/utsname.h> + +/* libdrm support is not yet upstream, so duplicate defs here for now */ + +struct INTERNAL_drm_i915_cgroup_param { + __s32 cgroup_fd; + __u32 flags; + __u64 param; +#define I915_CGROUP_PARAM_PRIORITY_OFFSET 0x1 + __s64 value; +}; + +#define INTERNAL_IOCTL_I915_CGROUP_SETPARAM \ + DRM_IOW(DRM_COMMAND_BASE + 0x39, struct INTERNAL_drm_i915_cgroup_param) + +static char tmp[PATH_MAX], *cgrp2dir = NULL; +static int cgrp2fd = -1; +static int drm_fd = -1; + +/* Figure out where (if) cgroups-v2 is mounted on this machine. */ +static void +find_cgroup2(void) +{ + FILE *f; + char *from, *path, *type; + + f = fopen("/proc/mounts", "r"); + igt_assert(f); + + while (fgets(tmp, sizeof(tmp), f)) { + from = strtok(tmp, " "); + if (!from) continue; + + path = strtok(NULL, " "); + if (!path) continue; + + type = strtok(NULL, " "); + if (strcmp(type, "cgroup2") == 0) { + cgrp2dir = path; + cgrp2fd = open(cgrp2dir, O_DIRECTORY|O_RDONLY); + break; + } + } + + fclose(f); + + igt_skip_on_f(!cgrp2dir, "cgroups-v2 is not mounted\n"); + igt_skip_on_f(!cgrp2fd, "Insufficient fs permissions on cgroup2 dir\n"); +} + +static char tmp_cgroup[PATH_MAX]; + +static int +create_tmp_cgroup(void) +{ + char *dirname; + int fd; + + snprintf(tmp_cgroup, sizeof(tmp_cgroup), "%s/igt_cgroup_XXXXXX", + cgrp2dir); + dirname = mkdtemp(tmp_cgroup); + igt_assert(dirname); + + fd = open(dirname, O_DIRECTORY|O_RDONLY); + igt_assert(fd >= 0); + + return fd; +} + +static void +rm_tmp_cgroup(int fd) +{ + close(fd); + rmdir(tmp_cgroup); +} + +static int +set_prio(int fd, int prio) +{ + struct INTERNAL_drm_i915_cgroup_param req; + + req.cgroup_fd = fd; + req.flags = 0; + req.param = I915_CGROUP_PARAM_PRIORITY_OFFSET; + req.value = prio; + + return drmIoctl(drm_fd, INTERNAL_IOCTL_I915_CGROUP_SETPARAM, &req); +} + +igt_main +{ + char other_file[PATH_MAX]; + int ret, fd; + + igt_fixture { + find_cgroup2(); + drm_fd = drm_open_driver_master(DRIVER_INTEL); + } + + /* Standard request to set priority. Should succeed */ + igt_subtest_f("set-prio") { + fd = create_tmp_cgroup(); + ret = set_prio(fd, 123); + igt_fail_on(ret); + rm_tmp_cgroup(fd); + } + + /* Use an invalid parameter ID. Should fail. */ + igt_subtest_f("bad-param") { + struct INTERNAL_drm_i915_cgroup_param req; + + fd = create_tmp_cgroup(); + req.cgroup_fd = fd; + req.flags = 0; + req.param = 0xDEADBEEF; + req.value = 123; + + ret = drmIoctl(drm_fd, INTERNAL_IOCTL_I915_CGROUP_SETPARAM, &req); + igt_assert(ret < 0 && errno == EINVAL); + + rm_tmp_cgroup(fd); + } + + /* Attempt to set prio with insufficient permissions. Should fail */ + igt_subtest_f("insufficient-permissions") { + igt_skip_on_f(geteuid() == 0, + "Permissions always succeed for root\n"); + + fd = create_tmp_cgroup(); + fchmod(fd, 0); + ret = set_prio(fd, 123); + igt_assert(ret < 0 && errno == EACCES); + rm_tmp_cgroup(fd); + } + + /* + * Pass fd for a cgroup control file instead of cgroup directory itself. + * Should fail. + */ + igt_subtest_f("control-file-fd") { + int fd2; + + fd = create_tmp_cgroup(); + snprintf(other_file, sizeof(other_file), + "%s/cgroup.procs", tmp_cgroup); + fd2 = open(other_file, O_RDONLY); + igt_assert(fd2 >= 0); + + ret = set_prio(fd2, 123); + igt_assert(ret < 0 && errno == EBADF); + + close(fd2); + rm_tmp_cgroup(fd); + } + + /* + * Pass an fd for a non-cgroup directory. Should fail. + * Note that we rely on /tmp being available and writable. + */ + igt_subtest_f("non-cgroup-fd") { + char *dirname; + + strcpy(other_file, "/tmp/igt_XXXXXX"); + dirname = mkdtemp(other_file); + igt_assert(dirname); + + fd = open(dirname, O_DIRECTORY|O_RDONLY); + igt_assert(fd >= 0); + + ret = set_prio(fd, 123); + igt_assert(ret < 0 && errno == EBADF); + + close(fd); + rmdir(dirname); + } + + /* + * Reload driver after setting priority. Should pass. + * + * The priority data will be lost across reload, but the goal is to + * make sure we don't panic during driver removal or subsequent + * assignment of a new priority to the existing cgroup. + */ + igt_subtest_f("cgroup-reload") { + fd = create_tmp_cgroup(); + ret = set_prio(fd, 123); + igt_fail_on(ret); + + ret = igt_i915_driver_unload(); + igt_fail_on(ret); + ret = igt_i915_driver_load(NULL); + igt_fail_on(ret); + + ret = set_prio(fd, 456); + igt_fail_on(ret); + + rm_tmp_cgroup(fd); + } +} -- 2.14.3 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx