/*
 *	linux/mm/mincore.c
 *
 * Copyright (C) 1994-2006  Linus Torvalds
 */

/*
 * The mincore() system call.
 */
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/syscalls.h>
#include <linux/swap.h>
#include <linux/swapops.h>
#include <linux/hugetlb.h>

#include <asm/uaccess.h>
#include <asm/pgtable.h>

/*
 * Later we can get more picky about what "in core" means precisely.
 * For now, simply check to see if the page is in the page cache,
 * and is up to date; i.e. that no page-in operation would be required
 * at this time if an application were to map and access this page.
 */
static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff)
{
	unsigned char present = 0;
	struct page *page;

	/*
	 * When tmpfs swaps out a page from a file, any process mapping that
	 * file will not get a swp_entry_t in its pte, but rather it is like
	 * any other file mapping (ie. marked !present and faulted in with
	 * tmpfs's .fault). So swapped out tmpfs mappings are tested here.
	 *
	 * However when tmpfs moves the page from pagecache and into swapcache,
	 * it is still in core, but the find_get_page below won't find it.
	 * No big deal, but make a note of it.
	 */
	page = find_get_page(mapping, pgoff);
	if (page) {
		present = PageUptodate(page);
		page_cache_release(page);
	}

	return present;
}

/*
 * Do a chunk of "sys_mincore()". We've already checked
 * all the arguments, we hold the mmap semaphore: we should
 * just return the amount of info we're asked for.
 */
static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pages)
{
	pgd_t *pgd;
	pud_t *pud;
	pmd_t *pmd;
	pte_t *ptep;
	spinlock_t *ptl;
	unsigned long nr;
	int i;
	pgoff_t pgoff;
	struct vm_area_struct *vma = find_vma(current->mm, addr);

	/*
	 * find_vma() didn't find anything above us, or we're
	 * in an unmapped hole in the address space: ENOMEM.
	 */
	if (!vma || addr < vma->vm_start)
		return -ENOMEM;

#ifdef CONFIG_HUGETLB_PAGE
	if (is_vm_hugetlb_page(vma)) {
		struct hstate *h;
		unsigned long nr_huge;
		unsigned char present;

		i = 0;
		nr = min(pages, (vma->vm_end - addr) >> PAGE_SHIFT);
		h = hstate_vma(vma);
		nr_huge = ((addr + pages * PAGE_SIZE - 1) >> huge_page_shift(h))
			  - (addr >> huge_page_shift(h)) + 1;
		nr_huge = min(nr_huge,
			      (vma->vm_end - addr) >> huge_page_shift(h));
		while (1) {
			/* hugepage always in RAM for now,
			 * but generally it needs to be check */
			ptep = huge_pte_offset(current->mm,
					       addr & huge_page_mask(h));
			present = !!(ptep &&
				     !huge_pte_none(huge_ptep_get(ptep)));
			while (1) {
				vec[i++] = present;
				addr += PAGE_SIZE;
				/* reach buffer limit */
				if (i == nr)
					return nr;
				/* check hugepage border */
				if (!((addr & ~huge_page_mask(h))
				      >> PAGE_SHIFT))
					break;
			}
		}
		return nr;
	}
#endif

	/*
	 * Calculate how many pages there are left in the last level of the
	 * PTE array for our address.
	 */
	nr = PTRS_PER_PTE - ((addr >> PAGE_SHIFT) & (PTRS_PER_PTE-1));

	/*
	 * Don't overrun this vma
	 */
	nr = min(nr, (vma->vm_end - addr) >> PAGE_SHIFT);

	/*
	 * Don't return more than the caller asked for
	 */
	nr = min(nr, pages);

	pgd = pgd_offset(vma->vm_mm, addr);
	if (pgd_none_or_clear_bad(pgd))
		goto none_mapped;
	pud = pud_offset(pgd, addr);
	if (pud_none_or_clear_bad(pud))
		goto none_mapped;
	pmd = pmd_offset(pud, addr);
	if (pmd_none_or_clear_bad(pmd))
		goto none_mapped;

	ptep = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
	for (i = 0; i < nr; i++, ptep++, addr += PAGE_SIZE) {
		unsigned char present;
		pte_t pte = *ptep;

		if (pte_present(pte)) {
			present = 1;

		} else if (pte_none(pte)) {
			if (vma->vm_file) {
				pgoff = linear_page_index(vma, addr);
				present = mincore_page(vma->vm_file->f_mapping,
							pgoff);
			} else
				present = 0;

		} else if (pte_file(pte)) {
			pgoff = pte_to_pgoff(pte);
			present = mincore_page(vma->vm_file->f_mapping, pgoff);

		} else { /* pte is a swap entry */
			swp_entry_t entry = pte_to_swp_entry(pte);
			if (is_migration_entry(entry)) {
				/* migration entries are always uptodate */
				present = 1;
			} else {
#ifdef CONFIG_SWAP
				pgoff = entry.val;
				present = mincore_page(&swapper_space, pgoff);
#else
				WARN_ON(1);
				present = 1;
#endif
			}
		}

		vec[i] = present;
	}
	pte_unmap_unlock(ptep-1, ptl);

	return nr;

none_mapped:
	if (vma->vm_file) {
		pgoff = linear_page_index(vma, addr);
		for (i = 0; i < nr; i++, pgoff++)
			vec[i] = mincore_page(vma->vm_file->f_mapping, pgoff);
	} else {
		for (i = 0; i < nr; i++)
			vec[i] = 0;
	}

	return nr;
}

/*
 * The mincore(2) system call.
 *
 * mincore() returns the memory residency status of the pages in the
 * current process's address space specified by [addr, addr + len).
 * The status is returned in a vector of bytes.  The least significant
 * bit of each byte is 1 if the referenced page is in memory, otherwise
 * it is zero.
 *
 * Because the status of a page can change after mincore() checks it
 * but before it returns to the application, the returned vector may
 * contain stale information.  Only locked pages are guaranteed to
 * remain in memory.
 *
 * return values:
 *  zero    - success
 *  -EFAULT - vec points to an illegal address
 *  -EINVAL - addr is not a multiple of PAGE_CACHE_SIZE
 *  -ENOMEM - Addresses in the range [addr, addr + len] are
 *		invalid for the address space of this process, or
 *		specify one or more pages which are not currently
 *		mapped
 *  -EAGAIN - A kernel resource was temporarily unavailable.
 */
SYSCALL_DEFINE3(mincore, unsigned long, start, size_t, len,
		unsigned char __user *, vec)
{
	long retval;
	unsigned long pages;
	unsigned char *tmp;

	/* Check the start address: needs to be page-aligned.. */
 	if (start & ~PAGE_CACHE_MASK)
		return -EINVAL;

	/* ..and we need to be passed a valid user-space range */
	if (!access_ok(VERIFY_READ, (void __user *) start, len))
		return -ENOMEM;

	/* This also avoids any overflows on PAGE_CACHE_ALIGN */
	pages = len >> PAGE_SHIFT;
	pages += (len & ~PAGE_MASK) != 0;

	if (!access_ok(VERIFY_WRITE, vec, pages))
		return -EFAULT;

	tmp = (void *) __get_free_page(GFP_USER);
	if (!tmp)
		return -EAGAIN;

	retval = 0;
	while (pages) {
		/*
		 * Do at most PAGE_SIZE entries per iteration, due to
		 * the temporary buffer size.
		 */
		down_read(&current->mm->mmap_sem);
		retval = do_mincore(start, tmp, min(pages, PAGE_SIZE));
		up_read(&current->mm->mmap_sem);

		if (retval <= 0)
			break;
		if (copy_to_user(vec, tmp, retval)) {
			retval = -EFAULT;
			break;
		}
		pages -= retval;
		vec += retval;
		start += retval << PAGE_SHIFT;
		retval = 0;
	}
	free_page((unsigned long) tmp);
	return retval;
}
