Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01997bbc authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky
Browse files

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: default avatarGerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 127c1fef
Loading
Loading
Loading
Loading
+23 −58
Original line number Diff line number Diff line
@@ -182,7 +182,13 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
	end = start + len;
	if ((end < start) || (end > TASK_SIZE))
		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);
	pgdp = pgd_offset(mm, addr);
	do {
@@ -219,63 +225,22 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
			struct page **pages)
{
	struct mm_struct *mm = current->mm;
	unsigned long addr, len, end;
	unsigned long next;
	pgd_t *pgdp, pgd;
	int nr = 0;
	int nr, ret;

	start &= PAGE_MASK;
	addr = start;
	len = (unsigned long) nr_pages << PAGE_SHIFT;
	end = start + len;
	if ((end < start) || (end > TASK_SIZE))
		goto slow_irqon;

	/*
	 * local_irq_disable() 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_disable();
	pgdp = pgd_offset(mm, addr);
	do {
		pgd = *pgdp;
		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);
	nr = __get_user_pages_fast(start, nr_pages, write, pages);
	if (nr == nr_pages)
		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);
			     nr_pages - nr, 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;
		}

	if (nr > 0)
		ret = (ret < 0) ? nr : ret + nr;
	return ret;
}
}