kernels/linux-2.4.0/mm/filemap.c
/*
 * filemap_nopage() is invoked via the vma operations vector for a
 * mapped memory region to read in file data during a page fault.
 *
 * The goto's are kind of ugly, but this streamlines the normal case of having
 * it in the page cache, and handles the special cases reasonably without
 * having a lot of duplicated code.
 */
filemap_nopage() is invoked via the vma operations vector for a
mapped memory region to read in file data during a page fault.

The goto's are kind of ugly, but this streamlines the normal case of having
it in the page cache, and handles the special cases reasonably without
having a lot of duplicated code.
filemap_nopage () is invoked via the vma operations vector for a mapped memory region to read in file data during a page fault . The goto ' s are kind of ugly but this streamlines the normal case of having it in the page cache and handles the special cases reasonably without having a lot of duplicated code .
struct page * filemap_nopage(struct vm_area_struct * area,
	unsigned long address, int no_share)
{
	int error;
	struct file *file = area->vm_file;
	struct inode *inode = file->f_dentry->d_inode;
	struct address_space *mapping = inode->i_mapping;
	struct page *page, **hash, *old_page;
	unsigned long size, pgoff;
	pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
retry_all:
	size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
	if ((pgoff >= size) && (area->vm_mm == current->mm))
		return NULL;
	hash = page_hash(mapping, pgoff);
retry_find:
	page = __find_get_page(mapping, pgoff, hash);
	if (!page)
		goto no_cached_page;
	if (!Page_Uptodate(page))
		goto page_not_uptodate;
success:
	if (VM_SequentialReadHint(area))
		nopage_sequential_readahead(area, pgoff, size);
	old_page = page;
	if (no_share) {
		struct page *new_page = page_cache_alloc();
		if (new_page) {
			copy_user_highpage(new_page, old_page, address);
			flush_page_to_ram(new_page);
		} else
			new_page = NOPAGE_OOM;
		page_cache_release(page);
		return new_page;
	}
	flush_page_to_ram(old_page);
	return old_page;
no_cached_page:
	if ((pgoff < size) && !VM_RandomReadHint(area))
		error = read_cluster_nonblocking(file, pgoff, size);
	else
		error = page_cache_read(file, pgoff);
	if (error >= 0)
		goto retry_find;
	if (error == -ENOMEM)
		return NOPAGE_OOM;
	return NULL;
page_not_uptodate:
	lock_page(page);
	if (!page->mapping) {
		UnlockPage(page);
		page_cache_release(page);
		goto retry_all;
	}
	if (Page_Uptodate(page)) {
		UnlockPage(page);
		goto success;
	}
	if (!mapping->a_ops->readpage(file, page)) {
		wait_on_page(page);
		if (Page_Uptodate(page))
			goto success;
	}
	lock_page(page);
	if (!page->mapping) {
		UnlockPage(page);
		page_cache_release(page);
		goto retry_all;
	}
	if (Page_Uptodate(page)) {
		UnlockPage(page);
		goto success;
	}
	ClearPageError(page);
	if (!mapping->a_ops->readpage(file, page)) {
		wait_on_page(page);
		if (Page_Uptodate(page))
			goto success;
	}
	page_cache_release(page);
	return NULL;
}
struct page * filemap_nopage ( struct vm_area_struct * area , unsigned long address , int no_share ) { int error ; struct file * file = area -> vm_file ; struct inode * inode = file -> f_dentry -> d_inode ; struct address_space * mapping = inode -> i_mapping ; struct page * page , * * hash , * old_page ; unsigned long size , pgoff ; pgoff = ( ( address - area -> vm_start ) >> PAGE_CACHE_SHIFT ) + area -> vm_pgoff ; retry_all : size = ( inode -> i_size + PAGE_CACHE_SIZE - 1 ) >> PAGE_CACHE_SHIFT ; if ( ( pgoff >= size ) && ( area -> vm_mm == current -> mm ) ) return NULL ; hash = page_hash ( mapping , pgoff ) ; retry_find : page = __find_get_page ( mapping , pgoff , hash ) ; if ( ! page ) goto no_cached_page ; if ( ! Page_Uptodate ( page ) ) goto page_not_uptodate ; success : if ( VM_SequentialReadHint ( area ) ) nopage_sequential_readahead ( area , pgoff , size ) ; old_page = page ; if ( no_share ) { struct page * new_page = page_cache_alloc ( ) ; if ( new_page ) { copy_user_highpage ( new_page , old_page , address ) ; flush_page_to_ram ( new_page ) ; } else new_page = NOPAGE_OOM ; page_cache_release ( page ) ; return new_page ; } flush_page_to_ram ( old_page ) ; return old_page ; no_cached_page : if ( ( pgoff < size ) && ! VM_RandomReadHint ( area ) ) error = read_cluster_nonblocking ( file , pgoff , size ) ; else error = page_cache_read ( file , pgoff ) ; if ( error >= 0 ) goto retry_find ; if ( error == - ENOMEM ) return NOPAGE_OOM ; return NULL ; page_not_uptodate : lock_page ( page ) ; if ( ! page -> mapping ) { UnlockPage ( page ) ; page_cache_release ( page ) ; goto retry_all ; } if ( Page_Uptodate ( page ) ) { UnlockPage ( page ) ; goto success ; } if ( ! mapping -> a_ops -> readpage ( file , page ) ) { wait_on_page ( page ) ; if ( Page_Uptodate ( page ) ) goto success ; } lock_page ( page ) ; if ( ! page -> mapping ) { UnlockPage ( page ) ; page_cache_release ( page ) ; goto retry_all ; } if ( Page_Uptodate ( page ) ) { UnlockPage ( page ) ; goto success ; } ClearPageError ( page ) ; if ( ! mapping -> a_ops -> readpage ( file , page ) ) { wait_on_page ( page ) ; if ( Page_Uptodate ( page ) ) goto success ; } page_cache_release ( page ) ; return NULL ; }
filemap_nopage() is invoked via the vma operations vector for a
 mapped memory region to read in file data during a page fault.
filemap_nopage () is invoked via the vma operations vector for a mapped memory region to read in file data during a page fault .
/*
	 * An external ptracer can access pages that normally aren't
	 * accessible..
	 */ /*
	 * Do we have something in the page cache already?
	 */ /*
	 * Ok, found a page in the page cache, now we need to check
	 * that it's up-to-date.
	 */ /*
	 * Try read-ahead for sequential areas.
	 */ /*
	 * Found the page and have a reference on it, need to check sharing
	 * and possibly copy it over to another page..
	 */ /*
	 * If the requested offset is within our file, try to read a whole 
	 * cluster of pages at once.
	 *
	 * Otherwise, we're off the end of a privately mapped file,
	 * so we need to map a zero page.
	 */ /*
	 * The page we want has now been added to the page cache.
	 * In the unlikely event that someone removed it in the
	 * meantime, we'll just come back here and read it again.
	 */ /*
	 * An error return from page_cache_read can result if the
	 * system is low on memory, or a problem occurs while trying
	 * to schedule I/O.
	 */ /* Did it get unhashed while we waited for it? */ /* Did somebody else get it up-to-date? */ /*
	 * Umm, take care of errors if the page isn't up-to-date.
	 * Try to re-read it _once_. We do this synchronously,
	 * because there really aren't any performance issues here
	 * and we need to check for errors.
	 */ /* Somebody truncated the page on us? */ /* Somebody else successfully read it in? */ /*
	 * Things didn't work out. Return zero to tell the
	 * mm layer so, possibly freeing the page cache page first.
	 */