static void mincore_pte_range(struct vm_area_struct *vma, pmd_t *pmd, unsigned long addr, unsigned long end, unsigned char *vec) { unsigned long next; spinlock_t *ptl; pte_t *ptep; ptep = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); do { pte_t pte = *ptep; pgoff_t pgoff; next = addr + PAGE_SIZE; if (pte_none(pte)) mincore_unmapped_range(vma, addr, next, vec); else if (pte_present(pte)) *vec = 1; else if (pte_file(pte)) { pgoff = pte_to_pgoff(pte); *vec = 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 */ *vec = 1; } else { #ifdef CONFIG_SWAP pgoff = entry.val; *vec = mincore_page(&swapper_space, pgoff); #else WARN_ON(1); *vec = 1; #endif } } vec++; } while (ptep++, addr = next, addr != end); pte_unmap_unlock(ptep - 1, ptl); }
static void mincore_unmapped_range(struct vm_area_struct *vma, unsigned long addr, unsigned long end, unsigned char *vec) { unsigned long nr = (end - addr) >> PAGE_SHIFT; int i; if (vma->vm_file) { pgoff_t pgoff; 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; } }
/* * 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) { unsigned long i, nr, 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; /* * Ok, got it. But check whether it's a segment we support * mincore() on. Right now, we don't do any anonymous mappings. * * FIXME: This is just stupid. And returning ENOMEM is * stupid too. We should just look at the page tables. But * this is what we've traditionally done, so we'll just * continue doing it. */ if (!vma->vm_file) return -ENOMEM; /* * Calculate how many pages there are left in the vma, and * what the pgoff is for our address. */ nr = (vma->vm_end - addr) >> PAGE_SHIFT; if (nr > pages) nr = pages; pgoff = (addr - vma->vm_start) >> PAGE_SHIFT; pgoff += vma->vm_pgoff; /* And then we just fill the sucker in.. */ for (i = 0 ; i < nr; i++, pgoff++) vec[i] = mincore_page(vma, pgoff); return nr; }