/* Returns zero and the pfn at @pfn on success, -ve otherwise.  */
int follow_pfn(struct vm_area_struct *vma, unsigned long address, unsigned long *pfn)
/* Returns zero and the pfn at @pfn on success, -ve otherwise.  */
int follow_pfn(struct vm_area_struct *vma, unsigned long address, unsigned long *pfn)
{
	int ret = -EINVAL;
	spinlock_t *ptl;
	pte_t *ptep;
	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
		return ret;
	ret = follow_pte(vma->vm_mm, address, &ptep, &ptl);
	if (ret)
		return ret;
	*pfn = pte_pfn(*ptep);
	pte_unmap_unlock(ptep, ptl);
	return 0;
}