Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Fix a deadlock in the bttv driver

vidiocgmbuf() does this:
mutex_lock(&fh->cap.vb_lock);
retval = videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
V4L2_MEMORY_MMAP);

and videobuf_mmap_setup() then just does
mutex_lock(&q->vb_lock);
ret = __videobuf_mmap_setup(q, bcount, bsize, memory);
mutex_unlock(&q->vb_lock);

which is an obvious double-take deadlock.

This patch fixes this by having vidiocgmbuf() just call the
__videobuf_mmap_setup function instead.

Acked-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Reported-by: Koos Vriezen <koos.vriezen@gmail.com>
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Arjan van de Ven and committed by
Linus Torvalds
81b2dbca babd90b2

+6 -2
+1 -1
drivers/media/video/bt8xx/bttv-driver.c
··· 2613 2613 struct bttv_fh *fh = priv; 2614 2614 2615 2615 mutex_lock(&fh->cap.vb_lock); 2616 - retval = videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize, 2616 + retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize, 2617 2617 V4L2_MEMORY_MMAP); 2618 2618 if (retval < 0) { 2619 2619 mutex_unlock(&fh->cap.vb_lock);
+2 -1
drivers/media/video/videobuf-core.c
··· 331 331 } 332 332 333 333 /* Locking: Caller holds q->vb_lock */ 334 - static int __videobuf_mmap_setup(struct videobuf_queue *q, 334 + int __videobuf_mmap_setup(struct videobuf_queue *q, 335 335 unsigned int bcount, unsigned int bsize, 336 336 enum v4l2_memory memory) 337 337 { ··· 1129 1129 EXPORT_SYMBOL_GPL(videobuf_read_one); 1130 1130 EXPORT_SYMBOL_GPL(videobuf_poll_stream); 1131 1131 1132 + EXPORT_SYMBOL_GPL(__videobuf_mmap_setup); 1132 1133 EXPORT_SYMBOL_GPL(videobuf_mmap_setup); 1133 1134 EXPORT_SYMBOL_GPL(videobuf_mmap_free); 1134 1135 EXPORT_SYMBOL_GPL(videobuf_mmap_mapper);
+3
include/media/videobuf-core.h
··· 237 237 int videobuf_mmap_setup(struct videobuf_queue *q, 238 238 unsigned int bcount, unsigned int bsize, 239 239 enum v4l2_memory memory); 240 + int __videobuf_mmap_setup(struct videobuf_queue *q, 241 + unsigned int bcount, unsigned int bsize, 242 + enum v4l2_memory memory); 240 243 int videobuf_mmap_free(struct videobuf_queue *q); 241 244 int videobuf_mmap_mapper(struct videobuf_queue *q, 242 245 struct vm_area_struct *vma);