drm: Make drm_read() more robust against multithreaded races
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 4 Dec 2014 21:03:25 +0000 (21:03 +0000)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 21 Jan 2015 13:57:03 +0000 (14:57 +0100)
commitcdd1cf799bd24ac0a4184549601ae302267301c5
treebf666cc69457b61505a8c3528f8dd1a77de80979
parent01934c2a691882185b3021d437df13bcba07711d
drm: Make drm_read() more robust against multithreaded races

The current implementation of drm_read() faces a number of issues:

1. Upon an error, it consumes the event which may lead to the client
blocking.
2. Upon an error, it forgets about events already copied
3. If it fails to copy a single event with O_NONBLOCK it falls into a
infinite loop of reporting EAGAIN.
3. There is a race between multiple waiters and blocking reads of the
events list.

Here, we inline drm_dequeue_event() into drm_read() so that we can take
the spinlock around the list walking and event copying, and importantly
reorder the error handling to avoid the issues above.

Cc: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Testcase: igt/drm_read
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/drm_fops.c