s390/gup: reduce code duplication between [__]get_user_pages_fast functions
Just call __get_user_pages_fast() from get_user_pages_fast() like powerpc. This saves a lot of duplicated code. Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Родитель
127c1fefff
Коммит
01997bbc92
|
@ -182,7 +182,13 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
|
||||||
end = start + len;
|
end = start + len;
|
||||||
if ((end < start) || (end > TASK_SIZE))
|
if ((end < start) || (end > TASK_SIZE))
|
||||||
return 0;
|
return 0;
|
||||||
|
/*
|
||||||
|
* local_irq_save() doesn't prevent pagetable teardown, but does
|
||||||
|
* prevent the pagetables from being freed on s390.
|
||||||
|
*
|
||||||
|
* So long as we atomically load page table pointers versus teardown,
|
||||||
|
* we can follow the address down to the the page and take a ref on it.
|
||||||
|
*/
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
pgdp = pgd_offset(mm, addr);
|
pgdp = pgd_offset(mm, addr);
|
||||||
do {
|
do {
|
||||||
|
@ -219,63 +225,22 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
|
||||||
struct page **pages)
|
struct page **pages)
|
||||||
{
|
{
|
||||||
struct mm_struct *mm = current->mm;
|
struct mm_struct *mm = current->mm;
|
||||||
unsigned long addr, len, end;
|
int nr, ret;
|
||||||
unsigned long next;
|
|
||||||
pgd_t *pgdp, pgd;
|
|
||||||
int nr = 0;
|
|
||||||
|
|
||||||
start &= PAGE_MASK;
|
start &= PAGE_MASK;
|
||||||
addr = start;
|
nr = __get_user_pages_fast(start, nr_pages, write, pages);
|
||||||
len = (unsigned long) nr_pages << PAGE_SHIFT;
|
if (nr == nr_pages)
|
||||||
end = start + len;
|
return nr;
|
||||||
if ((end < start) || (end > TASK_SIZE))
|
|
||||||
goto slow_irqon;
|
|
||||||
|
|
||||||
/*
|
/* Try to get the remaining pages with get_user_pages */
|
||||||
* local_irq_disable() doesn't prevent pagetable teardown, but does
|
start += nr << PAGE_SHIFT;
|
||||||
* prevent the pagetables from being freed on s390.
|
pages += nr;
|
||||||
*
|
down_read(&mm->mmap_sem);
|
||||||
* So long as we atomically load page table pointers versus teardown,
|
ret = get_user_pages(current, mm, start,
|
||||||
* we can follow the address down to the the page and take a ref on it.
|
nr_pages - nr, write, 0, pages, NULL);
|
||||||
*/
|
up_read(&mm->mmap_sem);
|
||||||
local_irq_disable();
|
/* Have to be a bit careful with return values */
|
||||||
pgdp = pgd_offset(mm, addr);
|
if (nr > 0)
|
||||||
do {
|
ret = (ret < 0) ? nr : ret + nr;
|
||||||
pgd = *pgdp;
|
return ret;
|
||||||
barrier();
|
|
||||||
next = pgd_addr_end(addr, end);
|
|
||||||
if (pgd_none(pgd))
|
|
||||||
goto slow;
|
|
||||||
if (!gup_pud_range(pgdp, pgd, addr, next, write, pages, &nr))
|
|
||||||
goto slow;
|
|
||||||
} while (pgdp++, addr = next, addr != end);
|
|
||||||
local_irq_enable();
|
|
||||||
|
|
||||||
VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT);
|
|
||||||
return nr;
|
|
||||||
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
slow:
|
|
||||||
local_irq_enable();
|
|
||||||
slow_irqon:
|
|
||||||
/* Try to get the remaining pages with get_user_pages */
|
|
||||||
start += nr << PAGE_SHIFT;
|
|
||||||
pages += nr;
|
|
||||||
|
|
||||||
down_read(&mm->mmap_sem);
|
|
||||||
ret = get_user_pages(current, mm, start,
|
|
||||||
(end - start) >> PAGE_SHIFT, write, 0, pages, NULL);
|
|
||||||
up_read(&mm->mmap_sem);
|
|
||||||
|
|
||||||
/* Have to be a bit careful with return values */
|
|
||||||
if (nr > 0) {
|
|
||||||
if (ret < 0)
|
|
||||||
ret = nr;
|
|
||||||
else
|
|
||||||
ret += nr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче