Commit 89ab2d39 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

media: vb2: frame_vector.c: don't overwrite error code

get_vaddr_frames() first calls pin_user_pages_fast() and if
that fails tries follow_pfn(). But if that also fails, then
the error code from pin_user_pages_fast() is overwritten with
the error code from follow_pfn().

Specifically if pin_user_pages_fast() returns -ENOMEM, then
follow_pfn() will overwrite that with -EINVAL, which is very
confusing.

So store the error code from pin_user_pages_fast() and return
that if follow_pfn() returns -EINVAL. -EINVAL indicates that
the page is unsuitable for follow_pfn, so pin_user_pages_fast()
was the correct call to make, and that error code should be
returned instead.
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent fadecf79
...@@ -37,6 +37,7 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames, ...@@ -37,6 +37,7 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
{ {
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
struct vm_area_struct *vma; struct vm_area_struct *vma;
int ret_pin_user_pages_fast = 0;
int ret = 0; int ret = 0;
int err; int err;
...@@ -56,6 +57,7 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames, ...@@ -56,6 +57,7 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
vec->is_pfns = false; vec->is_pfns = false;
goto out_unlocked; goto out_unlocked;
} }
ret_pin_user_pages_fast = ret;
mmap_read_lock(mm); mmap_read_lock(mm);
vec->got_ref = false; vec->got_ref = false;
...@@ -71,7 +73,18 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames, ...@@ -71,7 +73,18 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
while (ret < nr_frames && start + PAGE_SIZE <= vma->vm_end) { while (ret < nr_frames && start + PAGE_SIZE <= vma->vm_end) {
err = follow_pfn(vma, start, &nums[ret]); err = follow_pfn(vma, start, &nums[ret]);
if (err) { if (err) {
if (ret == 0) if (ret)
goto out;
// If follow_pfn() returns -EINVAL, then this
// is not an IO mapping or a raw PFN mapping.
// In that case, return the original error from
// pin_user_pages_fast(). Otherwise this
// function would return -EINVAL when
// pin_user_pages_fast() returned -ENOMEM,
// which makes debugging hard.
if (err == -EINVAL && ret_pin_user_pages_fast)
ret = ret_pin_user_pages_fast;
else
ret = err; ret = err;
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment