mm: migration: add migrate_entry_wait_huge()
[linux-3.10.git] / mm / filemap.c
index 3843445..7905fe7 100644 (file)
@@ -35,6 +35,9 @@
 #include <linux/cleancache.h>
 #include "internal.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/filemap.h>
+
 /*
  * FIXME: remove all knowledge of the buffer layer from the core VM
  */
@@ -113,6 +116,7 @@ void __delete_from_page_cache(struct page *page)
 {
        struct address_space *mapping = page->mapping;
 
+       trace_mm_filemap_delete_from_page_cache(page);
        /*
         * if we're uptodate, flush out into the cleancache, otherwise
         * invalidate any existing cleancache entries.  We can't leave
@@ -184,6 +188,17 @@ static int sleep_on_page_killable(void *word)
        return fatal_signal_pending(current) ? -EINTR : 0;
 }
 
+static int filemap_check_errors(struct address_space *mapping)
+{
+       int ret = 0;
+       /* Check for outstanding write errors */
+       if (test_and_clear_bit(AS_ENOSPC, &mapping->flags))
+               ret = -ENOSPC;
+       if (test_and_clear_bit(AS_EIO, &mapping->flags))
+               ret = -EIO;
+       return ret;
+}
+
 /**
  * __filemap_fdatawrite_range - start writeback on mapping dirty pages in range
  * @mapping:   address space structure to write
@@ -265,10 +280,10 @@ int filemap_fdatawait_range(struct address_space *mapping, loff_t start_byte,
        pgoff_t end = end_byte >> PAGE_CACHE_SHIFT;
        struct pagevec pvec;
        int nr_pages;
-       int ret = 0;
+       int ret2, ret = 0;
 
        if (end_byte < start_byte)
-               return 0;
+               goto out;
 
        pagevec_init(&pvec, 0);
        while ((index <= end) &&
@@ -291,12 +306,10 @@ int filemap_fdatawait_range(struct address_space *mapping, loff_t start_byte,
                pagevec_release(&pvec);
                cond_resched();
        }
-
-       /* Check for outstanding write errors */
-       if (test_and_clear_bit(AS_ENOSPC, &mapping->flags))
-               ret = -ENOSPC;
-       if (test_and_clear_bit(AS_EIO, &mapping->flags))
-               ret = -EIO;
+out:
+       ret2 = filemap_check_errors(mapping);
+       if (!ret)
+               ret = ret2;
 
        return ret;
 }
@@ -337,6 +350,8 @@ int filemap_write_and_wait(struct address_space *mapping)
                        if (!err)
                                err = err2;
                }
+       } else {
+               err = filemap_check_errors(mapping);
        }
        return err;
 }
@@ -368,6 +383,8 @@ int filemap_write_and_wait_range(struct address_space *mapping,
                        if (!err)
                                err = err2;
                }
+       } else {
+               err = filemap_check_errors(mapping);
        }
        return err;
 }
@@ -464,6 +481,7 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
                        mapping->nrpages++;
                        __inc_zone_page_state(page, NR_FILE_PAGES);
                        spin_unlock_irq(&mapping->tree_lock);
+                       trace_mm_filemap_add_to_page_cache(page);
                } else {
                        page->mapping = NULL;
                        /* Leave page->index set: truncation relies upon it */
@@ -1607,13 +1625,13 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
         * Do we have something in the page cache already?
         */
        page = find_get_page(mapping, offset);
-       if (likely(page)) {
+       if (likely(page) && !(vmf->flags & FAULT_FLAG_TRIED)) {
                /*
                 * We found the page, so try async readahead before
                 * waiting for the lock.
                 */
                do_async_mmap_readahead(vma, ra, file, page, offset);
-       } else {
+       } else if (!page) {
                /* No page in the page cache at all */
                do_sync_mmap_readahead(vma, ra, file, offset);
                count_vm_event(PGMAJFAULT);
@@ -1711,7 +1729,7 @@ EXPORT_SYMBOL(filemap_fault);
 int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct page *page = vmf->page;
-       struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
+       struct inode *inode = file_inode(vma->vm_file);
        int ret = VM_FAULT_LOCKED;
 
        sb_start_pagefault(inode->i_sb);
@@ -1728,6 +1746,7 @@ int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
         * see the dirty page and writeprotect it again.
         */
        set_page_dirty(page);
+       wait_for_stable_page(page);
 out:
        sb_end_pagefault(inode->i_sb);
        return ret;
@@ -1737,6 +1756,7 @@ EXPORT_SYMBOL(filemap_page_mkwrite);
 const struct vm_operations_struct generic_file_vm_ops = {
        .fault          = filemap_fault,
        .page_mkwrite   = filemap_page_mkwrite,
+       .remap_pages    = generic_file_remap_pages,
 };
 
 /* This is used for a general mmap of a disk file */
@@ -1749,7 +1769,6 @@ int generic_file_mmap(struct file * file, struct vm_area_struct * vma)
                return -ENOEXEC;
        file_accessed(file);
        vma->vm_ops = &generic_file_vm_ops;
-       vma->vm_flags |= VM_CAN_NONLINEAR;
        return 0;
 }
 
@@ -2056,7 +2075,7 @@ EXPORT_SYMBOL(iov_iter_fault_in_readable);
 /*
  * Return the count of just the current iov_iter segment.
  */
-size_t iov_iter_single_seg_count(struct iov_iter *i)
+size_t iov_iter_single_seg_count(const struct iov_iter *i)
 {
        const struct iovec *iov = i->iov;
        if (i->nr_segs == 1)
@@ -2274,7 +2293,7 @@ repeat:
                return NULL;
        }
 found:
-       wait_on_page_writeback(page);
+       wait_for_stable_page(page);
        return page;
 }
 EXPORT_SYMBOL(grab_cache_page_write_begin);
@@ -2527,7 +2546,6 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 
        BUG_ON(iocb->ki_pos != pos);
 
-       sb_start_write(inode->i_sb);
        mutex_lock(&inode->i_mutex);
        ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
        mutex_unlock(&inode->i_mutex);
@@ -2539,7 +2557,6 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                if (err < 0 && ret > 0)
                        ret = err;
        }
-       sb_end_write(inode->i_sb);
        return ret;
 }
 EXPORT_SYMBOL(generic_file_aio_write);