0a7476
From a3e0637aa224b31438a8ae550344362ee02a327b Mon Sep 17 00:00:00 2001
0a7476
Message-Id: <a3e0637aa224b31438a8ae550344362ee02a327b@dist-git>
0a7476
From: Erik Skultety <eskultet@redhat.com>
0a7476
Date: Tue, 9 Apr 2019 08:34:25 +0200
0a7476
Subject: [PATCH] util: Introduce virHostGetDRMRenderNode helper
0a7476
MIME-Version: 1.0
0a7476
Content-Type: text/plain; charset=UTF-8
0a7476
Content-Transfer-Encoding: 8bit
0a7476
0a7476
This is the first step towards libvirt picking the first available
0a7476
render node instead of QEMU. It also makes sense for us to be able to do
0a7476
that, since we allow specifying the node directly for SPICE, so if
0a7476
there's no render node specified by the user, we should pick the first
0a7476
available one. The algorithm used for that is essentially the same as
0a7476
the one QEMU uses.
0a7476
0a7476
Signed-off-by: Erik Skultety <eskultet@redhat.com>
0a7476
Reviewed-by: Ján Tomko <jtomko@redhat.com>
0a7476
(cherry picked from commit 394809694a5bcb6e1e6890f360c60993c0b63a74)
0a7476
0a7476
https: //bugzilla.redhat.com/show_bug.cgi?id=1628892
0a7476
Signed-off-by: Erik Skultety <eskultet@redhat.com>
0a7476
Message-Id: <48159f44f12685eb8c52061e09c27e37a5a157ea.1554791287.git.eskultet@redhat.com>
0a7476
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
0a7476
---
0a7476
 src/libvirt_private.syms |  1 +
0a7476
 src/util/virutil.c       | 53 ++++++++++++++++++++++++++++++++++++++++
0a7476
 src/util/virutil.h       |  2 ++
0a7476
 3 files changed, 56 insertions(+)
0a7476
0a7476
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
0a7476
index af9b61fbdc..6655dfdecc 100644
0a7476
--- a/src/libvirt_private.syms
0a7476
+++ b/src/libvirt_private.syms
0a7476
@@ -3116,6 +3116,7 @@ virGetUserName;
0a7476
 virGetUserRuntimeDirectory;
0a7476
 virGetUserShell;
0a7476
 virHexToBin;
0a7476
+virHostGetDRMRenderNode;
0a7476
 virHostHasIOMMU;
0a7476
 virIndexToDiskName;
0a7476
 virIsDevMapperDevice;
0a7476
diff --git a/src/util/virutil.c b/src/util/virutil.c
0a7476
index a908422feb..b25d2a5ca4 100644
0a7476
--- a/src/util/virutil.c
0a7476
+++ b/src/util/virutil.c
0a7476
@@ -2115,3 +2115,56 @@ virHostHasIOMMU(void)
0a7476
     VIR_DIR_CLOSE(iommuDir);
0a7476
     return ret;
0a7476
 }
0a7476
+
0a7476
+
0a7476
+/**
0a7476
+ * virHostGetDRMRenderNode:
0a7476
+ *
0a7476
+ * Picks the first DRM render node available. Missing DRI or missing DRM render
0a7476
+ * nodes in the system results in an error.
0a7476
+ *
0a7476
+ * Returns an absolute path to the first render node available or NULL in case
0a7476
+ * of an error with the error being reported.
0a7476
+ * Caller is responsible for freeing the result string.
0a7476
+ *
0a7476
+ */
0a7476
+char *
0a7476
+virHostGetDRMRenderNode(void)
0a7476
+{
0a7476
+    char *ret = NULL;
0a7476
+    DIR *driDir = NULL;
0a7476
+    const char *driPath = "/dev/dri";
0a7476
+    struct dirent *ent = NULL;
0a7476
+    int dirErr = 0;
0a7476
+    bool have_rendernode = false;
0a7476
+
0a7476
+    if (virDirOpen(&driDir, driPath) < 0)
0a7476
+        return NULL;
0a7476
+
0a7476
+    while ((dirErr = virDirRead(driDir, &ent, driPath)) > 0) {
0a7476
+        if (ent->d_type != DT_CHR)
0a7476
+            continue;
0a7476
+
0a7476
+        if (STRPREFIX(ent->d_name, "renderD")) {
0a7476
+            have_rendernode = true;
0a7476
+            break;
0a7476
+        }
0a7476
+    }
0a7476
+
0a7476
+    if (dirErr < 0)
0a7476
+        goto cleanup;
0a7476
+
0a7476
+    /* even if /dev/dri exists, there might be no renderDX nodes available */
0a7476
+    if (!have_rendernode) {
0a7476
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
0a7476
+                       _("No DRM render nodes available"));
0a7476
+        goto cleanup;
0a7476
+    }
0a7476
+
0a7476
+    if (virAsprintf(&ret, "%s/%s", driPath, ent->d_name) < 0)
0a7476
+        goto cleanup;
0a7476
+
0a7476
+ cleanup:
0a7476
+    VIR_DIR_CLOSE(driDir);
0a7476
+    return ret;
0a7476
+}
0a7476
diff --git a/src/util/virutil.h b/src/util/virutil.h
0a7476
index 1ba9635bd9..284c713be4 100644
0a7476
--- a/src/util/virutil.h
0a7476
+++ b/src/util/virutil.h
0a7476
@@ -218,6 +218,8 @@ unsigned long long virMemoryMaxValue(bool ulong) ATTRIBUTE_NOINLINE;
0a7476
 
0a7476
 bool virHostHasIOMMU(void);
0a7476
 
0a7476
+char *virHostGetDRMRenderNode(void);
0a7476
+
0a7476
 /**
0a7476
  * VIR_ASSIGN_IS_OVERFLOW:
0a7476
  * @rvalue: value that is checked (evaluated twice)
0a7476
-- 
0a7476
2.21.0
0a7476