V4L/DVB (3672): Fix memory leak in dvr open
The dvr device could be opened multiple times simultaneously in O_RDONLY mode. Each open after the first would allocate a new dvr buffer (1880 KB) and leak the old buffer. The first close would de-allocate the dvr buffer and cause all other open dvrs to stop working. This patch allows only a single O_RDONLY open of the drv device, as per the API specification. Multiple O_WRONLY opens are still allowed and don't appear to cause any problems. Signed-off-by: Trent Piepho <xyzzy@speakeasy.org> Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
2f03ee8e6b
commit
5e85bd057f
@@ -141,12 +141,18 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
|
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
|
||||||
void *mem = vmalloc(DVR_BUFFER_SIZE);
|
void *mem;
|
||||||
|
if (!dvbdev->readers) {
|
||||||
|
mutex_unlock(&dmxdev->mutex);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
mem = vmalloc(DVR_BUFFER_SIZE);
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
mutex_unlock(&dmxdev->mutex);
|
mutex_unlock(&dmxdev->mutex);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
|
dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
|
||||||
|
dvbdev->readers--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
|
if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
|
||||||
@@ -184,6 +190,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
|
|||||||
dmxdev->dvr_orig_fe);
|
dmxdev->dvr_orig_fe);
|
||||||
}
|
}
|
||||||
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
|
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
|
||||||
|
dvbdev->readers++;
|
||||||
if (dmxdev->dvr_buffer.data) {
|
if (dmxdev->dvr_buffer.data) {
|
||||||
void *mem = dmxdev->dvr_buffer.data;
|
void *mem = dmxdev->dvr_buffer.data;
|
||||||
mb();
|
mb();
|
||||||
@@ -1029,8 +1036,7 @@ static struct file_operations dvb_dvr_fops = {
|
|||||||
|
|
||||||
static struct dvb_device dvbdev_dvr = {
|
static struct dvb_device dvbdev_dvr = {
|
||||||
.priv = NULL,
|
.priv = NULL,
|
||||||
.users = 1,
|
.readers = 1,
|
||||||
.writers = 1,
|
|
||||||
.fops = &dvb_dvr_fops
|
.fops = &dvb_dvr_fops
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user