Commit d0217ac0 authored by Nick Piggin's avatar Nick Piggin Committed by Linus Torvalds

mm: fault feedback #1

Change ->fault prototype.  We now return an int, which contains
VM_FAULT_xxx code in the low byte, and FAULT_RET_xxx code in the next byte.
 FAULT_RET_ code tells the VM whether a page was found, whether it has been
locked, and potentially other things.  This is not quite the way he wanted
it yet, but that's changed in the next patch (which requires changes to
arch code).

This means we no longer set VM_CAN_INVALIDATE in the vma in order to say
that a page is locked which requires filemap_nopage to go away (because we
can no longer remain backward compatible without that flag), but we were
going to do that anyway.

struct fault_data is renamed to struct vm_fault as Linus asked. address
is now a void __user * that we should firmly encourage drivers not to use
without really good reason.

The page is now returned via a page pointer in the vm_fault struct.
Signed-off-by: default avatarNick Piggin <npiggin@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ed2f2f9b
......@@ -135,26 +135,8 @@ Who: Greg Kroah-Hartman <gregkh@suse.de>
---------------------------
What: filemap_nopage, filemap_populate
When: April 2007
Why: These legacy interfaces no longer have any callers in the kernel and
any functionality provided can be provided with filemap_fault. The
removal schedule is short because they are a big maintainence burden
and have some bugs.
Who: Nick Piggin <npiggin@suse.de>
---------------------------
What: vm_ops.populate, install_page
When: April 2007
Why: These legacy interfaces no longer have any callers in the kernel and
any functionality provided can be provided with vm_ops.fault.
Who: Nick Piggin <npiggin@suse.de>
---------------------------
What: vm_ops.nopage
When: February 2008, provided in-kernel callers have been converted
When: Soon, provided in-kernel callers have been converted
Why: This interface is replaced by vm_ops.fault, but it has been around
forever, is used by a lot of drivers, and doesn't cost much to
maintain.
......
......@@ -510,7 +510,7 @@ More details about quota locking can be found in fs/dquot.c.
prototypes:
void (*open)(struct vm_area_struct*);
void (*close)(struct vm_area_struct*);
struct page *(*fault)(struct vm_area_struct*, struct fault_data *);
int (*fault)(struct vm_area_struct*, struct vm_fault *);
struct page *(*nopage)(struct vm_area_struct*, unsigned long, int *);
int (*page_mkwrite)(struct vm_area_struct *, struct page *);
......
......@@ -364,8 +364,6 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
else
vma->vm_ops = &gfs2_vm_ops_private;
vma->vm_flags |= VM_CAN_INVALIDATE|VM_CAN_NONLINEAR;
gfs2_glock_dq_uninit(&i_gh);
return error;
......
......@@ -27,13 +27,12 @@
#include "trans.h"
#include "util.h"
static struct page *gfs2_private_fault(struct vm_area_struct *vma,
struct fault_data *fdata)
static int gfs2_private_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct gfs2_inode *ip = GFS2_I(vma->vm_file->f_mapping->host);
set_bit(GIF_PAGED, &ip->i_flags);
return filemap_fault(vma, fdata);
return filemap_fault(vma, vmf);
}
static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
......@@ -104,55 +103,55 @@ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
return error;
}
static struct page *gfs2_sharewrite_fault(struct vm_area_struct *vma,
struct fault_data *fdata)
static int gfs2_sharewrite_fault(struct vm_area_struct *vma,
struct vm_fault *vmf)
{
struct file *file = vma->vm_file;
struct gfs2_file *gf = file->private_data;
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
struct gfs2_holder i_gh;
struct page *result = NULL;
int alloc_required;
int error;
int ret = VM_FAULT_MINOR;
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
if (error)
return NULL;
goto out;
set_bit(GIF_PAGED, &ip->i_flags);
set_bit(GIF_SW_PAGED, &ip->i_flags);
error = gfs2_write_alloc_required(ip,
(u64)fdata->pgoff << PAGE_CACHE_SHIFT,
(u64)vmf->pgoff << PAGE_CACHE_SHIFT,
PAGE_CACHE_SIZE, &alloc_required);
if (error) {
fdata->type = VM_FAULT_OOM; /* XXX: are these right? */
goto out;
ret = VM_FAULT_OOM; /* XXX: are these right? */
goto out_unlock;
}
set_bit(GFF_EXLOCK, &gf->f_flags);
result = filemap_fault(vma, fdata);
ret = filemap_fault(vma, vmf);
clear_bit(GFF_EXLOCK, &gf->f_flags);
if (!result)
goto out;
if (ret & (VM_FAULT_ERROR | FAULT_RET_NOPAGE))
goto out_unlock;
if (alloc_required) {
error = alloc_page_backing(ip, result);
/* XXX: do we need to drop page lock around alloc_page_backing?*/
error = alloc_page_backing(ip, vmf->page);
if (error) {
if (vma->vm_flags & VM_CAN_INVALIDATE)
unlock_page(result);
page_cache_release(result);
fdata->type = VM_FAULT_OOM;
result = NULL;
goto out;
if (ret & FAULT_RET_LOCKED)
unlock_page(vmf->page);
page_cache_release(vmf->page);
ret = VM_FAULT_OOM;
goto out_unlock;
}
set_page_dirty(result);
set_page_dirty(vmf->page);
}
out:
out_unlock:
gfs2_glock_dq_uninit(&i_gh);
return result;
out:
return ret;
}
struct vm_operations_struct gfs2_vm_ops_private = {
......
......@@ -24,33 +24,35 @@
/*
* Fill in the supplied page for mmap
* XXX: how are we excluding truncate/invalidate here? Maybe need to lock
* page?
*/
static struct page* ncp_file_mmap_fault(struct vm_area_struct *area,
struct fault_data *fdata)
static int ncp_file_mmap_fault(struct vm_area_struct *area,
struct vm_fault *vmf)
{
struct file *file = area->vm_file;
struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct page* page;
char *pg_addr;
unsigned int already_read;
unsigned int count;
int bufsize;
int pos;
int pos; /* XXX: loff_t ? */
page = alloc_page(GFP_HIGHUSER); /* ncpfs has nothing against high pages
as long as recvmsg and memset works on it */
if (!page) {
fdata->type = VM_FAULT_OOM;
return NULL;
}
pg_addr = kmap(page);
pos = fdata->pgoff << PAGE_SHIFT;
/*
* ncpfs has nothing against high pages as long
* as recvmsg and memset works on it
*/
vmf->page = alloc_page(GFP_HIGHUSER);
if (!vmf->page)
return VM_FAULT_OOM;
pg_addr = kmap(vmf->page);
pos = vmf->pgoff << PAGE_SHIFT;
count = PAGE_SIZE;
if (fdata->address + PAGE_SIZE > area->vm_end) {
if ((unsigned long)vmf->virtual_address + PAGE_SIZE > area->vm_end) {
WARN_ON(1); /* shouldn't happen? */
count = area->vm_end - fdata->address;
count = area->vm_end - (unsigned long)vmf->virtual_address;
}
/* what we can read in one go */
bufsize = NCP_SERVER(inode)->buffer_size;
......@@ -85,17 +87,16 @@ static struct page* ncp_file_mmap_fault(struct vm_area_struct *area,
if (already_read < PAGE_SIZE)
memset(pg_addr + already_read, 0, PAGE_SIZE - already_read);
flush_dcache_page(page);
kunmap(page);
flush_dcache_page(vmf->page);
kunmap(vmf->page);
/*
* If I understand ncp_read_kernel() properly, the above always
* fetches from the network, here the analogue of disk.
* -- wli
*/
fdata->type = VM_FAULT_MAJOR;
count_vm_event(PGMAJFAULT);
return page;
return VM_FAULT_MAJOR;
}
static struct vm_operations_struct ncp_file_mmap =
......@@ -124,7 +125,6 @@ int ncp_mmap(struct file *file, struct vm_area_struct *vma)
return -EFBIG;
vma->vm_ops = &ncp_file_mmap;
vma->vm_flags |= VM_CAN_INVALIDATE;
file_accessed(file);
return 0;
}
......@@ -60,30 +60,28 @@ static inline int ocfs2_vm_op_unblock_sigs(sigset_t *oldset)
return sigprocmask(SIG_SETMASK, oldset, NULL);
}
static struct page *ocfs2_fault(struct vm_area_struct *area,
struct fault_data *fdata)
static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf)
{
struct page *page = NULL;
sigset_t blocked, oldset;
int ret;
int error, ret;
mlog_entry("(area=%p, page offset=%lu)\n", area, fdata->pgoff);
mlog_entry("(area=%p, page offset=%lu)\n", area, vmf->pgoff);
ret = ocfs2_vm_op_block_sigs(&blocked, &oldset);
if (ret < 0) {
fdata->type = VM_FAULT_SIGBUS;
mlog_errno(ret);
error = ocfs2_vm_op_block_sigs(&blocked, &oldset);
if (error < 0) {
mlog_errno(error);
ret = VM_FAULT_SIGBUS;
goto out;
}
page = filemap_fault(area, fdata);
ret = filemap_fault(area, vmf);
ret = ocfs2_vm_op_unblock_sigs(&oldset);
if (ret < 0)
mlog_errno(ret);
error = ocfs2_vm_op_unblock_sigs(&oldset);
if (error < 0)
mlog_errno(error);
out:
mlog_exit_ptr(page);
return page;
mlog_exit_ptr(vmf->page);
return ret;
}
static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
......@@ -225,7 +223,7 @@ int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
ocfs2_meta_unlock(file->f_dentry->d_inode, lock_level);
out:
vma->vm_ops = &ocfs2_file_vm_ops;
vma->vm_flags |= VM_CAN_INVALIDATE | VM_CAN_NONLINEAR;
vma->vm_flags |= VM_CAN_NONLINEAR;
return 0;
}
......@@ -212,20 +212,18 @@ xfs_file_fsync(
}
#ifdef CONFIG_XFS_DMAPI
STATIC struct page *
STATIC int
xfs_vm_fault(
struct vm_area_struct *vma,
struct fault_data *fdata)
struct vm_fault *vmf)
{
struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
bhv_vnode_t *vp = vn_from_inode(inode);
ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), vma, 0)) {
fdata->type = VM_FAULT_SIGBUS;
return NULL;
}
return filemap_fault(vma, fdata);
if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), vma, 0))
return VM_FAULT_SIGBUS;
return filemap_fault(vma, vmf);
}
#endif /* CONFIG_XFS_DMAPI */
......@@ -311,7 +309,7 @@ xfs_file_mmap(
struct vm_area_struct *vma)
{
vma->vm_ops = &xfs_file_vm_ops;
vma->vm_flags |= VM_CAN_INVALIDATE | VM_CAN_NONLINEAR;
vma->vm_flags |= VM_CAN_NONLINEAR;
#ifdef CONFIG_XFS_DMAPI
if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
......
......@@ -168,12 +168,7 @@ extern unsigned int kobjsize(const void *objp);
#define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */
#define VM_ALWAYSDUMP 0x04000000 /* Always include in core dumps */
#define VM_CAN_INVALIDATE 0x08000000 /* The mapping may be invalidated,
* eg. truncate or invalidate_inode_*.
* In this case, do_no_page must
* return with the page locked.
*/
#define VM_CAN_NONLINEAR 0x10000000 /* Has ->fault & does nonlinear pages */
#define VM_CAN_NONLINEAR 0x08000000 /* Has ->fault & does nonlinear pages */
#ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
#define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
......@@ -197,24 +192,44 @@ extern unsigned int kobjsize(const void *objp);
*/
extern pgprot_t protection_map[16];
#define FAULT_FLAG_WRITE 0x01
#define FAULT_FLAG_NONLINEAR 0x02
#define FAULT_FLAG_WRITE 0x01 /* Fault was a write access */
#define FAULT_FLAG_NONLINEAR 0x02 /* Fault was via a nonlinear mapping */
#define FAULT_RET_NOPAGE 0x0100 /* ->fault did not return a page. This
* can be used if the handler installs
* their own pte.
*/
#define FAULT_RET_LOCKED 0x0200 /* ->fault locked the page, caller must
* unlock after installing the mapping.
* This is used by pagecache in
* particular, where the page lock is
* used to synchronise against truncate
* and invalidate. Mutually exclusive
* with FAULT_RET_NOPAGE.
*/
/*
* fault_data is filled in the the pagefault handler and passed to the
* vma's ->fault function. That function is responsible for filling in
* 'type', which is the type of fault if a page is returned, or the type
* of error if NULL is returned.
* vm_fault is filled by the the pagefault handler and passed to the vma's
* ->fault function. The vma's ->fault is responsible for returning the
* VM_FAULT_xxx type which occupies the lowest byte of the return code, ORed
* with FAULT_RET_ flags that occupy the next byte and give details about
* how the fault was handled.
*
* pgoff should be used in favour of address, if possible. If pgoff is
* used, one may set VM_CAN_NONLINEAR in the vma->vm_flags to get
* nonlinear mapping support.
* pgoff should be used in favour of virtual_address, if possible. If pgoff
* is used, one may set VM_CAN_NONLINEAR in the vma->vm_flags to get nonlinear
* mapping support.
*/
struct fault_data {
unsigned long address;
pgoff_t pgoff;
unsigned int flags;
int type;
struct vm_fault {
unsigned int flags; /* FAULT_FLAG_xxx flags */
pgoff_t pgoff; /* Logical page offset based on vma */
void __user *virtual_address; /* Faulting virtual address */
struct page *page; /* ->fault handlers should return a
* page here, unless FAULT_RET_NOPAGE
* is set (which is also implied by
* VM_FAULT_OOM or SIGBUS).
*/
};
/*
......@@ -225,15 +240,11 @@ struct fault_data {
struct vm_operations_struct {
void (*open)(struct vm_area_struct * area);
void (*close)(struct vm_area_struct * area);
struct page *(*fault)(struct vm_area_struct *vma,
struct fault_data *fdata);
int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
struct page *(*nopage)(struct vm_area_struct *area,
unsigned long address, int *type);
unsigned long (*nopfn)(struct vm_area_struct *area,
unsigned long address);
int (*populate)(struct vm_area_struct *area, unsigned long address,
unsigned long len, pgprot_t prot, unsigned long pgoff,
int nonblock);
/* notification that a previously read-only page is about to become
* writable, if an error is returned it will cause a SIGBUS */
......@@ -700,8 +711,14 @@ static inline int page_mapped(struct page *page)
* Used to decide whether a process gets delivered SIGBUS or
* just gets major/minor fault counters bumped up.
*/
#define VM_FAULT_OOM 0x00
#define VM_FAULT_SIGBUS 0x01
/*
* VM_FAULT_ERROR is set for the error cases, to make some tests simpler.
*/
#define VM_FAULT_ERROR 0x20
#define VM_FAULT_OOM (0x00 | VM_FAULT_ERROR)
#define VM_FAULT_SIGBUS (0x01 | VM_FAULT_ERROR)
#define VM_FAULT_MINOR 0x02
#define VM_FAULT_MAJOR 0x03
......@@ -711,6 +728,11 @@ static inline int page_mapped(struct page *page)
*/
#define VM_FAULT_WRITE 0x10
/*
* Mask of VM_FAULT_ flags
*/
#define VM_FAULT_MASK 0xff
#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
extern void show_free_areas(void);
......@@ -793,8 +815,6 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
extern int vmtruncate(struct inode * inode, loff_t offset);
extern int vmtruncate_range(struct inode * inode, loff_t offset, loff_t end);
extern int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot);
extern int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned long pgoff, pgprot_t prot);
#ifdef CONFIG_MMU
extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma,
......@@ -1135,11 +1155,7 @@ extern void truncate_inode_pages_range(struct address_space *,
loff_t lstart, loff_t lend);
/* generic vm_area_ops exported for stackable file systems */
extern struct page *filemap_fault(struct vm_area_struct *, struct fault_data *);
extern struct page * __deprecated_for_modules
filemap_nopage(struct vm_area_struct *, unsigned long, int *);
extern int __deprecated_for_modules filemap_populate(struct vm_area_struct *,
unsigned long, unsigned long, pgprot_t, unsigned long, int);
extern int filemap_fault(struct vm_area_struct *, struct vm_fault *);
/* mm/page-writeback.c */
int write_one_page(struct page *page, int wait);
......
......@@ -224,13 +224,12 @@ static void shm_close(struct vm_area_struct *vma)
mutex_unlock(&shm_ids(ns).mutex);
}
static struct page *shm_fault(struct vm_area_struct *vma,
struct fault_data *fdata)
static int shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct file *file = vma->vm_file;
struct shm_file_data *sfd = shm_file_data(file);
return sfd->vm_ops->fault(vma, fdata);
return sfd->vm_ops->fault(vma, vmf);
}
#ifdef CONFIG_NUMA
......
......@@ -1302,8 +1302,8 @@ static int fastcall page_cache_read(struct file * file, unsigned long offset)
/**
* filemap_fault - read in file data for page fault handling
* @vma: user vma (not used)
* @fdata: the applicable fault_data
* @vma: vma in which the fault was taken
* @vmf: struct vm_fault containing details of the fault
*
* filemap_fault() is invoked via the vma operations vector for a
* mapped memory region to read in file data during a page fault.
......@@ -1312,7 +1312,7 @@ static int fastcall page_cache_read(struct file * file, unsigned long offset)
* it in the page cache, and handles the special cases reasonably without
* having a lot of duplicated code.
*/
struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
int error;
struct file *file = vma->vm_file;
......@@ -1322,13 +1322,12 @@ struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
struct page *page;
unsigned long size;
int did_readaround = 0;
int ret;
fdata->type = VM_FAULT_MINOR;
BUG_ON(!(vma->vm_flags & VM_CAN_INVALIDATE));
ret = VM_FAULT_MINOR;
size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
if (fdata->pgoff >= size)
if (vmf->pgoff >= size)
goto outside_data_content;
/* If we don't want any read-ahead, don't bother */
......@@ -1342,18 +1341,18 @@ struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
* For sequential accesses, we use the generic readahead logic.
*/
if (VM_SequentialReadHint(vma))
page_cache_readahead(mapping, ra, file, fdata->pgoff, 1);
page_cache_readahead(mapping, ra, file, vmf->pgoff, 1);
/*
* Do we have something in the page cache already?
*/
retry_find:
page = find_lock_page(mapping, fdata->pgoff);
page = find_lock_page(mapping, vmf->pgoff);
if (!page) {
unsigned long ra_pages;
if (VM_SequentialReadHint(vma)) {
handle_ra_miss(mapping, ra, fdata->pgoff);
handle_ra_miss(mapping, ra, vmf->pgoff);
goto no_cached_page;
}
ra->mmap_miss++;
......@@ -1370,7 +1369,7 @@ struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
* check did_readaround, as this is an inner loop.
*/
if (!did_readaround) {
fdata->type = VM_FAULT_MAJOR;
ret = VM_FAULT_MAJOR;
count_vm_event(PGMAJFAULT);
}
did_readaround = 1;
......@@ -1378,11 +1377,11 @@ struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
if (ra_pages) {
pgoff_t start = 0;
if (fdata->pgoff > ra_pages / 2)
start = fdata->pgoff - ra_pages / 2;
if (vmf->pgoff > ra_pages / 2)
start = vmf->pgoff - ra_pages / 2;
do_page_cache_readahead(mapping, file, start, ra_pages);
}
page = find_lock_page(mapping, fdata->pgoff);
page = find_lock_page(mapping, vmf->pgoff);
if (!page)
goto no_cached_page;
}
......@@ -1399,7 +1398,7 @@ struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
/* Must recheck i_size under page lock */
size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
if (unlikely(fdata->pgoff >= size)) {
if (unlikely(vmf->pgoff >= size)) {
unlock_page(page);
goto outside_data_content;
}
......@@ -1408,24 +1407,24 @@ struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
* Found the page and have a reference on it.
*/
mark_page_accessed(page);
return page;
vmf->page = page;
return ret | FAULT_RET_LOCKED;
outside_data_content:
/*
* An external ptracer can access pages that normally aren't
* accessible..
*/
if (vma->vm_mm == current->mm) {
fdata->type = VM_FAULT_SIGBUS;
return NULL;
}
if (vma->vm_mm == current->mm)
return VM_FAULT_SIGBUS;
/* Fall through to the non-read-ahead case */
no_cached_page:
/*
* We're only likely to ever get here if MADV_RANDOM is in
* effect.
*/
error = page_cache_read(file, fdata->pgoff);
error = page_cache_read(file, vmf->pgoff);
/*
* The page we want has now been added to the page cache.
......@@ -1441,15 +1440,13 @@ struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
* to schedule I/O.
*/
if (error == -ENOMEM)
fdata->type = VM_FAULT_OOM;
else
fdata->type = VM_FAULT_SIGBUS;
return NULL;
return VM_FAULT_OOM;
return VM_FAULT_SIGBUS;
page_not_uptodate:
/* IO error path */
if (!did_readaround) {
fdata->type = VM_FAULT_MAJOR;
ret = VM_FAULT_MAJOR;
count_vm_event(PGMAJFAULT);
}
......@@ -1468,206 +1465,10 @@ struct page *filemap_fault(struct vm_area_struct *vma, struct fault_data *fdata)
/* Things didn't work out. Return zero to tell the mm layer so. */
shrink_readahead_size_eio(file, ra);
fdata->type = VM_FAULT_SIGBUS;
return NULL;
return VM_FAULT_SIGBUS;
}
EXPORT_SYMBOL(filemap_fault);
/*
* filemap_nopage and filemap_populate are legacy exports that are not used
* in tree. Scheduled for removal.
*/
struct page *filemap_nopage(struct vm_area_struct *area,
unsigned long address, int *type)
{
struct page *page;
struct fault_data fdata;
fdata.address = address;
fdata.pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT)
+ area->vm_pgoff;
fdata.flags = 0;
page = filemap_fault(area, &fdata);
if (type)
*type = fdata.type;
return page;
}
EXPORT_SYMBOL(filemap_nopage);
static struct page * filemap_getpage(struct file *file, unsigned long pgoff,
int nonblock)
{
struct address_space *mapping = file->f_mapping;
struct page *page;
int error;
/*
* Do we have something in the page cache already?
*/
retry_find:
page = find_get_page(mapping, pgoff);
if (!page) {
if (nonblock)
return NULL;
goto no_cached_page;
}
/*