From: Josef Schlehofer <pepe.schlehofer@gmail.com>
To: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
Hyunwoo Kim <imv4bel@gmail.com>,
Hans Verkuil <hverkuil@kernel.org>,
stable@vger.kernel.org
Subject: [PATCH v2 5/6] media: dvb-core: dmxdev: wake up readers on release
Date: Sun, 4 Oct 2026 12:07:40 +0200 [thread overview]
Message-ID: <20261004100741.71711-6-pepe.schlehofer@gmail.com> (raw)
In-Reply-To: <20261004100741.71711-1-pepe.schlehofer@gmail.com>
dvb_dmxdev_release() sets dmxdev->exit and waits for open demux and DVR
files to close, but readers blocked in dvb_dmxdev_buffer_read() wait
only for data or buffer->error. Setting exit therefore does not wake a
blocked read or epoll wait. The release, for example on a USB
disconnect, then waits forever.
Wake the DVR and open filter wait queues on release, and make
dvb_dmxdev_buffer_read() also wait for exit and return -ENODEV once it
is set. Also return -ENODEV from dvb_demux_read() once exit is set, as
dvb_dvr_read() already does.
Check exit instead of storing -ENODEV in buffer->error. The buffer error
is cleared by the reader that reports it, and the section timeout and
ioctls such as DMX_STOP can overwrite or clear it. A second reader of
the same file could then miss the release and keep it waiting.
Blocking DMX_DQBUF waiters are not covered.
Fixes: 57861b432bda ("V4L/DVB (5511): Fix 2/3 for bug 7819: demux and dvr")
Cc: stable@vger.kernel.org
Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com>
---
v2: check dmxdev->exit in the readers instead of storing -ENODEV in the
buffer error. A reader could clear an -ENODEV set concurrently by the
release, as reported by Sashiko [1]. The section timeout and ioctls
such as DMX_STOP could also overwrite or clear it.
Pre-existing cases remain where the release waits for users that are
not woken up, such as a blocking DMX_DQBUF, or an ioctl that waits for
the filter mutex of a blocked read() while holding dmxdev->mutex. The
unlocked users check in dvb_dmxdev_release() also still races with a
concurrent close(), and waking the readers makes that race easier to
hit.
v1: https://lore.kernel.org/r/20260923001410.30297-6-pepe.schlehofer@gmail.com
[1] https://linuxtv.org/mailman3/hyperkitty/list/media-ci@linuxtv.org/message/N3XJE5MO4HP2LJYOKFHIRB564HATZCTI/
drivers/media/dvb-core/dmxdev.c | 36 +++++++++++++++++++++++++++------
1 file changed, 30 insertions(+), 6 deletions(-)
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index 6a825d9bae43..8a744a96bc08 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -50,7 +50,8 @@ static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf,
return dvb_ringbuffer_write(buf, src, len);
}
-static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
+static ssize_t dvb_dmxdev_buffer_read(struct dmxdev *dmxdev,
+ struct dvb_ringbuffer *src,
int non_blocking, char __user *buf,
size_t count, loff_t *ppos)
{
@@ -75,10 +76,16 @@ static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
ret = wait_event_interruptible(src->queue,
!dvb_ringbuffer_empty(src) ||
- (src->error != 0));
+ (src->error != 0) ||
+ dmxdev->exit);
if (ret < 0)
break;
+ if (dmxdev->exit) {
+ ret = -ENODEV;
+ break;
+ }
+
if (src->error) {
ret = src->error;
dvb_ringbuffer_flush(src);
@@ -274,7 +281,7 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
if (dmxdev->exit)
return -ENODEV;
- return dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
+ return dvb_dmxdev_buffer_read(dmxdev, &dmxdev->dvr_buffer,
file->f_flags & O_NONBLOCK,
buf, count, ppos);
}
@@ -998,7 +1005,7 @@ static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil,
hcount = 3 + dfil->todo;
if (hcount > count)
hcount = count;
- result = dvb_dmxdev_buffer_read(&dfil->buffer,
+ result = dvb_dmxdev_buffer_read(dfil->dev, &dfil->buffer,
file->f_flags & O_NONBLOCK,
buf, hcount, ppos);
if (result < 0) {
@@ -1019,7 +1026,7 @@ static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil,
}
if (count > dfil->todo)
count = dfil->todo;
- result = dvb_dmxdev_buffer_read(&dfil->buffer,
+ result = dvb_dmxdev_buffer_read(dfil->dev, &dfil->buffer,
file->f_flags & O_NONBLOCK,
buf, count, ppos);
if (result < 0)
@@ -1035,13 +1042,17 @@ dvb_demux_read(struct file *file, char __user *buf, size_t count,
struct dmxdev_filter *dmxdevfilter = file->private_data;
int ret;
+ if (dmxdevfilter->dev->exit)
+ return -ENODEV;
+
if (mutex_lock_interruptible(&dmxdevfilter->mutex))
return -ERESTARTSYS;
if (dmxdevfilter->type == DMXDEV_TYPE_SEC)
ret = dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos);
else
- ret = dvb_dmxdev_buffer_read(&dmxdevfilter->buffer,
+ ret = dvb_dmxdev_buffer_read(dmxdevfilter->dev,
+ &dmxdevfilter->buffer,
file->f_flags & O_NONBLOCK,
buf, count, ppos);
@@ -1457,8 +1468,21 @@ EXPORT_SYMBOL(dvb_dmxdev_init);
void dvb_dmxdev_release(struct dmxdev *dmxdev)
{
+ int i;
+
mutex_lock(&dmxdev->mutex);
dmxdev->exit = 1;
+
+ /*
+ * Wake up everyone blocked in read() or poll() on the demux and dvr
+ * devices, so that they get -ENODEV or EPOLLERR, close their file
+ * handles and let the waits below finish.
+ */
+ wake_up_all(&dmxdev->dvr_buffer.queue);
+ for (i = 0; i < dmxdev->filternum; i++) {
+ if (dmxdev->filter[i].state >= DMXDEV_STATE_ALLOCATED)
+ wake_up_all(&dmxdev->filter[i].buffer.queue);
+ }
mutex_unlock(&dmxdev->mutex);
if (dmxdev->dvbdev->users > 1) {
--
2.54.0 (Apple Git-157)
next prev parent reply other threads:[~2026-10-04 10:07 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-04 10:07 [PATCH v2 0/6] media: az6007/drxk/dvb-core: cope with a tuner unplugged while in use Josef Schlehofer
2026-10-04 10:07 ` [PATCH v2 1/6] media: az6007: fix CAM status polling after disconnect Josef Schlehofer
2026-10-04 10:07 ` [PATCH v2 2/6] media: az6007: propagate USB errors from I2C transfers Josef Schlehofer
2026-10-04 10:07 ` [PATCH v2 3/6] media: drxk: stop retrying after disconnect Josef Schlehofer
2026-10-04 10:07 ` [PATCH v2 4/6] media: drxk: stop accessing a disconnected device Josef Schlehofer
2026-10-04 10:07 ` Josef Schlehofer [this message]
2026-10-04 10:07 ` [PATCH v2 6/6] media: dvb-core: wake up CA users on release Josef Schlehofer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261004100741.71711-6-pepe.schlehofer@gmail.com \
--to=pepe.schlehofer@gmail.com \
--cc=hverkuil@kernel.org \
--cc=imv4bel@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®