1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 19 May 2020 15:30:29 +0200
Subject: [PATCH] virt: vbox: Add vbg_set_host_capabilities() helper function
Add vbg_set_host_capabilities() helper function, this is a preparation
patch for adding support for the VBGL_IOCTL_GUEST_CAPS_ACQUIRE ioctl.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Upstream Status: https://lore.kernel.org/lkml/20200520195440.38759-1-hdegoede@redhat.com/
---
drivers/virt/vboxguest/vboxguest_core.c | 79 ++++++++++++++-----------
1 file changed, 46 insertions(+), 33 deletions(-)
diff --git a/drivers/virt/vboxguest/vboxguest_core.c b/drivers/virt/vboxguest/vboxguest_core.c
index aee5eff229f2..15b3cb618c6e 100644
--- a/drivers/virt/vboxguest/vboxguest_core.c
+++ b/drivers/virt/vboxguest/vboxguest_core.c
@@ -661,6 +661,48 @@ static int vbg_reset_host_capabilities(struct vbg_dev *gdev)
return vbg_status_code_to_errno(rc);
}
+/**
+ * Set guest capabilities on the host.
+ * Must be called with gdev->session_mutex hold.
+ * Return: 0 or negative errno value.
+ * @gdev: The Guest extension device.
+ * @session: The session.
+ * @session_termination: Set if we're called by the session cleanup code.
+ */
+static int vbg_set_host_capabilities(struct vbg_dev *gdev,
+ struct vbg_session *session,
+ bool session_termination)
+{
+ struct vmmdev_mask *req;
+ u32 caps;
+ int rc;
+
+ WARN_ON(!mutex_is_locked(&gdev->session_mutex));
+
+ caps = gdev->set_guest_caps_tracker.mask;
+
+ if (gdev->guest_caps_host == caps)
+ return 0;
+
+ /* On termination the requestor is the kernel, as we're cleaning up. */
+ req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_GUEST_CAPABILITIES,
+ session_termination ? VBG_KERNEL_REQUEST :
+ session->requestor);
+ if (!req) {
+ gdev->guest_caps_host = U32_MAX;
+ return -ENOMEM;
+ }
+
+ req->or_mask = caps;
+ req->not_mask = ~caps;
+ rc = vbg_req_perform(gdev, req);
+ vbg_req_free(req, sizeof(*req));
+
+ gdev->guest_caps_host = (rc >= 0) ? caps : U32_MAX;
+
+ return vbg_status_code_to_errno(rc);
+}
+
/**
* Sets the guest capabilities for a session. Takes the session spinlock.
* Return: 0 or negative errno value.
@@ -678,23 +720,8 @@ static int vbg_set_session_capabilities(struct vbg_dev *gdev,
u32 or_mask, u32 not_mask,
bool session_termination)
{
- struct vmmdev_mask *req;
u32 changed, previous;
- int rc, ret = 0;
-
- /*
- * Allocate a request buffer before taking the spinlock, when
- * the session is being terminated the requestor is the kernel,
- * as we're cleaning up.
- */
- req = vbg_req_alloc(sizeof(*req), VMMDEVREQ_SET_GUEST_CAPABILITIES,
- session_termination ? VBG_KERNEL_REQUEST :
- session->requestor);
- if (!req) {
- if (!session_termination)
- return -ENOMEM;
- /* Ignore allocation failure, we must do session cleanup. */
- }
+ int ret = 0;
mutex_lock(&gdev->session_mutex);
@@ -709,23 +736,10 @@ static int vbg_set_session_capabilities(struct vbg_dev *gdev,
goto out;
vbg_track_bit_usage(&gdev->set_guest_caps_tracker, changed, previous);
- or_mask = gdev->set_guest_caps_tracker.mask;
-
- if (gdev->guest_caps_host == or_mask || !req)
- goto out;
-
- gdev->guest_caps_host = or_mask;
- req->or_mask = or_mask;
- req->not_mask = ~or_mask;
- rc = vbg_req_perform(gdev, req);
- if (rc < 0) {
- ret = vbg_status_code_to_errno(rc);
-
- /* Failed, roll back (unless it's session termination time). */
- gdev->guest_caps_host = U32_MAX;
- if (session_termination)
- goto out;
+ ret = vbg_set_host_capabilities(gdev, session, session_termination);
+ /* Roll back on failure, unless it's session termination time. */
+ if (ret < 0 && !session_termination) {
vbg_track_bit_usage(&gdev->set_guest_caps_tracker, changed,
session->set_guest_caps);
session->set_guest_caps = previous;
@@ -733,7 +747,6 @@ static int vbg_set_session_capabilities(struct vbg_dev *gdev,
out:
mutex_unlock(&gdev->session_mutex);
- vbg_req_free(req, sizeof(*req));
return ret;
}
--
2.26.2
|