]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.19.51/vfio-fix-warning-do-not-call-blocking-ops-when-task_.patch
Linux 4.19.51
[thirdparty/kernel/stable-queue.git] / releases / 4.19.51 / vfio-fix-warning-do-not-call-blocking-ops-when-task_.patch
1 From fbfc05061c443e73e5ad8d08c6c5e7416f94ff04 Mon Sep 17 00:00:00 2001
2 From: Farhan Ali <alifm@linux.ibm.com>
3 Date: Wed, 3 Apr 2019 14:22:27 -0400
4 Subject: vfio: Fix WARNING "do not call blocking ops when !TASK_RUNNING"
5
6 [ Upstream commit 41be3e2618174fdf3361e49e64f2bf530f40c6b0 ]
7
8 vfio_dev_present() which is the condition to
9 wait_event_interruptible_timeout(), will call vfio_group_get_device
10 and try to acquire the mutex group->device_lock.
11
12 wait_event_interruptible_timeout() will set the state of the current
13 task to TASK_INTERRUPTIBLE, before doing the condition check. This
14 means that we will try to acquire the mutex while already in a
15 sleeping state. The scheduler warns us by giving the following
16 warning:
17
18 [ 4050.264464] ------------[ cut here ]------------
19 [ 4050.264508] do not call blocking ops when !TASK_RUNNING; state=1 set at [<00000000b33c00e2>] prepare_to_wait_event+0x14a/0x188
20 [ 4050.264529] WARNING: CPU: 12 PID: 35924 at kernel/sched/core.c:6112 __might_sleep+0x76/0x90
21 ....
22
23 4050.264756] Call Trace:
24 [ 4050.264765] ([<000000000017bbaa>] __might_sleep+0x72/0x90)
25 [ 4050.264774] [<0000000000b97edc>] __mutex_lock+0x44/0x8c0
26 [ 4050.264782] [<0000000000b9878a>] mutex_lock_nested+0x32/0x40
27 [ 4050.264793] [<000003ff800d7abe>] vfio_group_get_device+0x36/0xa8 [vfio]
28 [ 4050.264803] [<000003ff800d87c0>] vfio_del_group_dev+0x238/0x378 [vfio]
29 [ 4050.264813] [<000003ff8015f67c>] mdev_remove+0x3c/0x68 [mdev]
30 [ 4050.264825] [<00000000008e01b0>] device_release_driver_internal+0x168/0x268
31 [ 4050.264834] [<00000000008de692>] bus_remove_device+0x162/0x190
32 [ 4050.264843] [<00000000008daf42>] device_del+0x1e2/0x368
33 [ 4050.264851] [<00000000008db12c>] device_unregister+0x64/0x88
34 [ 4050.264862] [<000003ff8015ed84>] mdev_device_remove+0xec/0x130 [mdev]
35 [ 4050.264872] [<000003ff8015f074>] remove_store+0x6c/0xa8 [mdev]
36 [ 4050.264881] [<000000000046f494>] kernfs_fop_write+0x14c/0x1f8
37 [ 4050.264890] [<00000000003c1530>] __vfs_write+0x38/0x1a8
38 [ 4050.264899] [<00000000003c187c>] vfs_write+0xb4/0x198
39 [ 4050.264908] [<00000000003c1af2>] ksys_write+0x5a/0xb0
40 [ 4050.264916] [<0000000000b9e270>] system_call+0xdc/0x2d8
41 [ 4050.264925] 4 locks held by sh/35924:
42 [ 4050.264933] #0: 000000001ef90325 (sb_writers#4){.+.+}, at: vfs_write+0x9e/0x198
43 [ 4050.264948] #1: 000000005c1ab0b3 (&of->mutex){+.+.}, at: kernfs_fop_write+0x1cc/0x1f8
44 [ 4050.264963] #2: 0000000034831ab8 (kn->count#297){++++}, at: kernfs_remove_self+0x12e/0x150
45 [ 4050.264979] #3: 00000000e152484f (&dev->mutex){....}, at: device_release_driver_internal+0x5c/0x268
46 [ 4050.264993] Last Breaking-Event-Address:
47 [ 4050.265002] [<000000000017bbaa>] __might_sleep+0x72/0x90
48 [ 4050.265010] irq event stamp: 7039
49 [ 4050.265020] hardirqs last enabled at (7047): [<00000000001cee7a>] console_unlock+0x6d2/0x740
50 [ 4050.265029] hardirqs last disabled at (7054): [<00000000001ce87e>] console_unlock+0xd6/0x740
51 [ 4050.265040] softirqs last enabled at (6416): [<0000000000b8fe26>] __udelay+0xb6/0x100
52 [ 4050.265049] softirqs last disabled at (6415): [<0000000000b8fe06>] __udelay+0x96/0x100
53 [ 4050.265057] ---[ end trace d04a07d39d99a9f9 ]---
54
55 Let's fix this as described in the article
56 https://lwn.net/Articles/628628/.
57
58 Signed-off-by: Farhan Ali <alifm@linux.ibm.com>
59 [remove now redundant vfio_dev_present()]
60 Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
61 Signed-off-by: Sasha Levin <sashal@kernel.org>
62 ---
63 drivers/vfio/vfio.c | 30 ++++++++++--------------------
64 1 file changed, 10 insertions(+), 20 deletions(-)
65
66 diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
67 index 64833879f75d..7a386fb30bf1 100644
68 --- a/drivers/vfio/vfio.c
69 +++ b/drivers/vfio/vfio.c
70 @@ -34,6 +34,7 @@
71 #include <linux/uaccess.h>
72 #include <linux/vfio.h>
73 #include <linux/wait.h>
74 +#include <linux/sched/signal.h>
75
76 #define DRIVER_VERSION "0.3"
77 #define DRIVER_AUTHOR "Alex Williamson <alex.williamson@redhat.com>"
78 @@ -904,30 +905,17 @@ void *vfio_device_data(struct vfio_device *device)
79 }
80 EXPORT_SYMBOL_GPL(vfio_device_data);
81
82 -/* Given a referenced group, check if it contains the device */
83 -static bool vfio_dev_present(struct vfio_group *group, struct device *dev)
84 -{
85 - struct vfio_device *device;
86 -
87 - device = vfio_group_get_device(group, dev);
88 - if (!device)
89 - return false;
90 -
91 - vfio_device_put(device);
92 - return true;
93 -}
94 -
95 /*
96 * Decrement the device reference count and wait for the device to be
97 * removed. Open file descriptors for the device... */
98 void *vfio_del_group_dev(struct device *dev)
99 {
100 + DEFINE_WAIT_FUNC(wait, woken_wake_function);
101 struct vfio_device *device = dev_get_drvdata(dev);
102 struct vfio_group *group = device->group;
103 void *device_data = device->device_data;
104 struct vfio_unbound_dev *unbound;
105 unsigned int i = 0;
106 - long ret;
107 bool interrupted = false;
108
109 /*
110 @@ -964,6 +952,8 @@ void *vfio_del_group_dev(struct device *dev)
111 * interval with counter to allow the driver to take escalating
112 * measures to release the device if it has the ability to do so.
113 */
114 + add_wait_queue(&vfio.release_q, &wait);
115 +
116 do {
117 device = vfio_group_get_device(group, dev);
118 if (!device)
119 @@ -975,12 +965,10 @@ void *vfio_del_group_dev(struct device *dev)
120 vfio_device_put(device);
121
122 if (interrupted) {
123 - ret = wait_event_timeout(vfio.release_q,
124 - !vfio_dev_present(group, dev), HZ * 10);
125 + wait_woken(&wait, TASK_UNINTERRUPTIBLE, HZ * 10);
126 } else {
127 - ret = wait_event_interruptible_timeout(vfio.release_q,
128 - !vfio_dev_present(group, dev), HZ * 10);
129 - if (ret == -ERESTARTSYS) {
130 + wait_woken(&wait, TASK_INTERRUPTIBLE, HZ * 10);
131 + if (signal_pending(current)) {
132 interrupted = true;
133 dev_warn(dev,
134 "Device is currently in use, task"
135 @@ -989,8 +977,10 @@ void *vfio_del_group_dev(struct device *dev)
136 current->comm, task_pid_nr(current));
137 }
138 }
139 - } while (ret <= 0);
140
141 + } while (1);
142 +
143 + remove_wait_queue(&vfio.release_q, &wait);
144 /*
145 * In order to support multiple devices per group, devices can be
146 * plucked from the group while other devices in the group are still
147 --
148 2.20.1
149