DRI2 backend of Mesa started relying more on libdrm to open DRM
devices nodes and opening multiple fds on a single node. This change
keeps track of up to 10 fds so that stub works again.

Signed-off-by: Lionel Landwerlin <lionel.g.landwer...@intel.com>
---
 intel_stub.c | 98 +++++++++++++++++++++++++---------------------------
 1 file changed, 48 insertions(+), 50 deletions(-)

diff --git a/intel_stub.c b/intel_stub.c
index 8b8db64..9ac8ad3 100644
--- a/intel_stub.c
+++ b/intel_stub.c
@@ -23,9 +23,11 @@
 
 #define _GNU_SOURCE /* for RTLD_NEXT */
 
+#include <assert.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdarg.h>
 #include <errno.h>
@@ -37,6 +39,8 @@
 #include <dlfcn.h>
 #include <i915_drm.h>
 
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
 static void *(*libc_mmap)(void *addr, size_t len, int prot, int flags,
                           int fildes, off_t off);
 static void *(*libc_mmap64)(void *addr, size_t len, int prot, int flags,
@@ -52,7 +56,39 @@ static int (*libc__fxstat64)(int ver, int fd, struct stat64 
*buf);
 static int (*libc_fcntl)(int fd, int cmd, int param);
 static ssize_t (*libc_readlink)(const char *pathname, char *buf, size_t 
bufsiz);
 
-static int drm_fd = 0x0000BEEF;
+int open64(const char*, int, ...) __attribute__((alias("open")));
+int fcntl64(int fd, int cmd, ...) __attribute__((alias("fcntl")));
+void* mmap64(void*, size_t, int, int, int, off_t) 
__attribute__((alias("mmap")));
+
+static int drm_fds[10];
+static int n_drm_fds = 0;
+
+static int create_drm_fd(int flags, mode_t mode)
+{
+       assert(n_drm_fds < ARRAY_SIZE(drm_fds));
+       drm_fds[n_drm_fds++] = libc_open("/dev/null", flags, mode);
+       return drm_fds[n_drm_fds - 1];
+}
+
+static void remove_drm_fd(int fd)
+{
+       for (int i = 0; i < n_drm_fds; i++) {
+               if (fd == drm_fds[i]) {
+                       for (int j = i + 1; j < n_drm_fds; j++)
+                               drm_fds[j - 1] = drm_fds[j];
+                       n_drm_fds--;
+                       return;
+               }
+       }
+}
+
+static bool is_drm_fd(int fd)
+{
+       for (int i = 0; i < n_drm_fds; i++)
+               if (fd == drm_fds[i])
+                       return true;
+       return false;
+}
 
 #define DRM_MAJOR 226
 
@@ -89,45 +125,27 @@ open(const char *path, int flags, ...)
        va_list args;
        mode_t mode;
 
-       if (strcmp(path, "/dev/dri/renderD128") == 0)
-              return drm_fd;
-
        va_start(args, flags);
        mode = va_arg(args, int);
        va_end(args);
 
-       return libc_open(path, flags, mode);
-}
-
-__attribute__ ((visibility ("default"))) int
-open64(const char *path, int flags, ...)
-{
-       va_list args;
-       mode_t mode;
-
        if (strcmp(path, "/dev/dri/renderD128") == 0)
-              return drm_fd;
-
-       va_start(args, flags);
-       mode = va_arg(args, int);
-       va_end(args);
+              return create_drm_fd(flags, mode);
 
-       return libc_open64(path, flags, mode);
+       return libc_open(path, flags, mode);
 }
 
 __attribute__ ((visibility ("default"))) int
 close(int fd)
 {
-       if (fd == drm_fd)
-               return 0;
-
+       remove_drm_fd(fd);
        return libc_close(fd);
 }
 
 __attribute__ ((visibility ("default"))) int
 fstat(int fd, struct stat *buf)
 {
-       if (fd == drm_fd) {
+       if (is_drm_fd(fd)) {
                buf->st_mode = S_IFCHR |
                        (S_IRWXG | S_IRGRP |  S_IRWXU | S_IRUSR);
                buf->st_uid = 0;
@@ -141,7 +159,7 @@ fstat(int fd, struct stat *buf)
 __attribute__ ((visibility ("default"))) int
 fstat64(int fd, struct stat64 *buf)
 {
-       if (fd == drm_fd) {
+       if (is_drm_fd(fd)) {
                buf->st_mode = S_IFCHR |
                        (S_IRWXG | S_IRGRP |  S_IRWXU | S_IRUSR);
                buf->st_uid = 0;
@@ -155,7 +173,7 @@ fstat64(int fd, struct stat64 *buf)
 __attribute__ ((visibility ("default"))) int
 __fxstat(int ver, int fd, struct stat *buf)
 {
-       if (fd == drm_fd) {
+       if (is_drm_fd(fd)) {
                buf->st_mode = S_IFCHR |
                        (S_IRWXG | S_IRGRP |  S_IRWXU | S_IRUSR);
                buf->st_rdev = makedev(DRM_MAJOR, 0);
@@ -170,7 +188,7 @@ __fxstat(int ver, int fd, struct stat *buf)
 __attribute__ ((visibility ("default"))) int
 __fxstat64(int ver, int fd, struct stat64 *buf)
 {
-       if (fd == drm_fd) {
+       if (is_drm_fd(fd)) {
                buf->st_mode = S_IFCHR |
                        (S_IRWXG | S_IRGRP |  S_IRWXU | S_IRUSR);
                buf->st_rdev = makedev(DRM_MAJOR, 0);
@@ -188,8 +206,8 @@ fcntl(int fd, int cmd, ...)
        va_list args;
        int param;
 
-       if (fd == drm_fd && cmd == F_DUPFD_CLOEXEC)
-               return drm_fd;
+       if (is_drm_fd(fd) && cmd == F_DUPFD_CLOEXEC)
+               return create_drm_fd(O_RDWR, O_CLOEXEC);
 
        va_start(args, cmd);
        param = va_arg(args, int);
@@ -202,7 +220,7 @@ __attribute__ ((visibility ("default"))) void *
 mmap(void *addr, size_t len, int prot, int flags,
      int fildes, off_t off)
 {
-        if (fildes == drm_fd) {
+        if (is_drm_fd(fildes)) {
                 return libc_mmap(NULL, len, prot, flags | MAP_ANONYMOUS,
                                  -1, 0);
         } else {
@@ -210,19 +228,6 @@ mmap(void *addr, size_t len, int prot, int flags,
         }
 }
 
-__attribute__ ((visibility ("default"))) void *
-mmap64(void *addr, size_t len, int prot, int flags,
-       int fildes, off_t off)
-{
-        if (fildes == drm_fd) {
-                return libc_mmap64(NULL, len, prot, flags | MAP_ANONYMOUS,
-                                   -1, 0);
-        } else {
-                return libc_mmap64(addr, len, prot, flags, fildes, off);
-        }
-}
-
-
 __attribute__ ((visibility ("default"))) ssize_t
 readlink(const char *pathname, char *buf, size_t bufsiz)
 {
@@ -237,20 +242,13 @@ ioctl(int fd, unsigned long request, ...)
 {
        va_list args;
        void *argp;
-       struct stat buf;
        char *pci_id;
 
        va_start(args, request);
        argp = va_arg(args, void *);
        va_end(args);
 
-       if (_IOC_TYPE(request) == DRM_IOCTL_BASE &&
-           drm_fd != fd && libc_fstat(fd, &buf) == 0 &&
-           (buf.st_mode & S_IFMT) == S_IFCHR && major(buf.st_rdev) == 
DRM_MAJOR) {
-               drm_fd = fd;
-       }
-
-       if (fd == drm_fd) {
+       if (is_drm_fd(fd)) {
                switch (request) {
                 case DRM_IOCTL_VERSION:
                        return dispatch_version(fd, request, argp);
-- 
2.20.1

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to