AppArmor: fix oops in apparmor_setprocattr
[firefly-linux-kernel-4.4.55.git] / mm / filemap.c
index c974a2863897564d097b8e7c2ecfce4928b64ef1..d7b10578a64ba39b2862464f71d6439609c6fa22 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */
 #include <linux/memcontrol.h>
 #include <linux/mm_inline.h> /* for page_is_file_cache() */
+#include <linux/cleancache.h>
 #include "internal.h"
 
 /*
@@ -118,6 +119,16 @@ void __delete_from_page_cache(struct page *page)
 {
        struct address_space *mapping = page->mapping;
 
+       /*
+        * if we're uptodate, flush out into the cleancache, otherwise
+        * invalidate any existing cleancache entries.  We can't leave
+        * stale data around in the cleancache once our page is gone
+        */
+       if (PageUptodate(page) && PageMappedToDisk(page))
+               cleancache_put_page(page);
+       else
+               cleancache_flush_page(mapping, page);
+
        radix_tree_delete(&mapping->page_tree, page->index);
        page->mapping = NULL;
        mapping->nrpages--;
@@ -1559,14 +1570,14 @@ static void do_sync_mmap_readahead(struct vm_area_struct *vma,
        if (!ra->ra_pages)
                return;
 
-       if (VM_SequentialReadHint(vma) ||
-                       offset - 1 == (ra->prev_pos >> PAGE_CACHE_SHIFT)) {
+       if (VM_SequentialReadHint(vma)) {
                page_cache_sync_readahead(mapping, ra, file, offset,
                                          ra->ra_pages);
                return;
        }
 
-       if (ra->mmap_miss < INT_MAX)
+       /* Avoid banging the cache line if not needed */
+       if (ra->mmap_miss < MMAP_LOTSAMISS * 10)
                ra->mmap_miss++;
 
        /*
@@ -1582,7 +1593,7 @@ static void do_sync_mmap_readahead(struct vm_area_struct *vma,
        ra_pages = max_sane_readahead(ra->ra_pages);
        ra->start = max_t(long, 0, offset - ra_pages / 2);
        ra->size = ra_pages;
-       ra->async_size = 0;
+       ra->async_size = ra_pages / 4;
        ra_submit(ra, mapping, file);
 }
 
@@ -1650,6 +1661,7 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                /* No page in the page cache at all */
                do_sync_mmap_readahead(vma, ra, file, offset);
                count_vm_event(PGMAJFAULT);
+               mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT);
                ret = VM_FAULT_MAJOR;
 retry_find:
                page = find_get_page(mapping, offset);
@@ -1688,7 +1700,6 @@ retry_find:
                return VM_FAULT_SIGBUS;
        }
 
-       ra->prev_pos = (loff_t)offset << PAGE_CACHE_SHIFT;
        vmf->page = page;
        return ret | VM_FAULT_LOCKED;
 
@@ -1971,16 +1982,26 @@ static int __remove_suid(struct dentry *dentry, int kill)
 int file_remove_suid(struct file *file)
 {
        struct dentry *dentry = file->f_path.dentry;
-       int killsuid = should_remove_suid(dentry);
-       int killpriv = security_inode_need_killpriv(dentry);
+       struct inode *inode = dentry->d_inode;
+       int killsuid;
+       int killpriv;
        int error = 0;
 
+       /* Fast path for nothing security related */
+       if (IS_NOSEC(inode))
+               return 0;
+
+       killsuid = should_remove_suid(dentry);
+       killpriv = security_inode_need_killpriv(dentry);
+
        if (killpriv < 0)
                return killpriv;
        if (killpriv)
                error = security_inode_killpriv(dentry);
        if (!error && killsuid)
                error = __remove_suid(dentry, killsuid);
+       if (!error)
+               inode->i_flags |= S_NOSEC;
 
        return error;
 }
@@ -2316,7 +2337,7 @@ struct page *grab_cache_page_write_begin(struct address_space *mapping,
 repeat:
        page = find_lock_page(mapping, index);
        if (page)
-               return page;
+               goto found;
 
        page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~gfp_notmask);
        if (!page)
@@ -2329,6 +2350,8 @@ repeat:
                        goto repeat;
                return NULL;
        }
+found:
+       wait_on_page_writeback(page);
        return page;
 }
 EXPORT_SYMBOL(grab_cache_page_write_begin);