diff options
author | Tomasz Figa <tfiga@chromium.org> | 2017-06-19 06:53:43 +0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-06-20 15:11:48 +0300 |
commit | 758d90e161382c134b7cbd5f724df4de02f3c67e (patch) | |
tree | b2e6d2940b2f6b161560d2d2fbeafeb78e7cfac3 /drivers/media/v4l2-core/v4l2-ioctl.c | |
parent | d295c6a460cd2ac63597691288ed044f5cfa8a6e (diff) | |
download | linux-758d90e161382c134b7cbd5f724df4de02f3c67e.tar.xz |
[media] v4l2-core: Use kvmalloc() for potentially big allocations
There are multiple places where arrays or otherwise variable sized
buffer are allocated through V4L2 core code, including things like
controls, memory pages, staging buffers for ioctls and so on. Such
allocations can potentially require an order > 0 allocation from the
page allocator, which is not guaranteed to be fulfilled and is likely to
fail on a system with severe memory fragmentation (e.g. a system with
very long uptime).
Since the memory being allocated is intended to be used by the CPU
exclusively, we can consider using vmalloc() as a fallback and this is
exactly what the recently merged kvmalloc() helpers do. A kmalloc() call
is still attempted, even for order > 0 allocations, but it is done
with __GFP_NORETRY and __GFP_NOWARN, with expectation of failing if
requested memory is not available instantly. Only then the vmalloc()
fallback is used. This should give us fast and more reliable allocations
even on systems with higher memory pressure and/or more fragmentation,
while still retaining the same performance level on systems not
suffering from such conditions.
While at it, replace explicit array size calculations on changed
allocations with kvmalloc_array().
Purposedly not touching videobuf1, as it is deprecated, has only few
users remaining and would rather be seen removed instead.
Signed-off-by: Tomasz Figa <tfiga@chromium.org>
Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-ioctl.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index ce40183d9daa..6eabd915aff6 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -12,6 +12,7 @@ * Mauro Carvalho Chehab <mchehab@infradead.org> (version 2) */ +#include <linux/mm.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/types.h> @@ -2817,7 +2818,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, parg = sbuf; } else { /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); + mbuf = kvmalloc(_IOC_SIZE(cmd), GFP_KERNEL); if (NULL == mbuf) return -ENOMEM; parg = mbuf; @@ -2866,7 +2867,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, * array) fits into sbuf (so that mbuf will still remain * unused up to here). */ - mbuf = kmalloc(array_size, GFP_KERNEL); + mbuf = kvmalloc(array_size, GFP_KERNEL); err = -ENOMEM; if (NULL == mbuf) goto out_array_args; @@ -2911,7 +2912,7 @@ out_array_args: } out: - kfree(mbuf); + kvfree(mbuf); return err; } EXPORT_SYMBOL(video_usercopy); |