affs: fix remount failure when there are no options changed
[linux-2.6-block.git] / mm / shmem.c
index 719bd6b88d98eaf0958ec57ddb152f22de0f74d0..a36144909b2840213c087f3eb32fbd10d7c880ee 100644 (file)
@@ -101,7 +101,6 @@ struct shmem_falloc {
 enum sgp_type {
        SGP_READ,       /* don't exceed i_size, don't allocate page */
        SGP_CACHE,      /* don't exceed i_size, may allocate page */
-       SGP_DIRTY,      /* like SGP_CACHE, but set new page dirty */
        SGP_WRITE,      /* may exceed i_size, may allocate !Uptodate page */
        SGP_FALLOC,     /* like SGP_WRITE, but make existing page Uptodate */
 };
@@ -122,13 +121,14 @@ static bool shmem_should_replace_page(struct page *page, gfp_t gfp);
 static int shmem_replace_page(struct page **pagep, gfp_t gfp,
                                struct shmem_inode_info *info, pgoff_t index);
 static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
-       struct page **pagep, enum sgp_type sgp, gfp_t gfp, int *fault_type);
+               struct page **pagep, enum sgp_type sgp,
+               gfp_t gfp, struct mm_struct *fault_mm, int *fault_type);
 
 static inline int shmem_getpage(struct inode *inode, pgoff_t index,
-       struct page **pagep, enum sgp_type sgp, int *fault_type)
+               struct page **pagep, enum sgp_type sgp)
 {
        return shmem_getpage_gfp(inode, index, pagep, sgp,
-                       mapping_gfp_mask(inode->i_mapping), fault_type);
+               mapping_gfp_mask(inode->i_mapping), NULL, NULL);
 }
 
 static inline struct shmem_sb_info *SHMEM_SB(struct super_block *sb)
@@ -169,7 +169,7 @@ static inline int shmem_reacct_size(unsigned long flags,
 
 /*
  * ... whereas tmpfs objects are accounted incrementally as
- * pages are allocated, in order to allow huge sparse files.
+ * pages are allocated, in order to allow large sparse files.
  * shmem_getpage reports shmem_acct_block failure as -ENOSPC not -ENOMEM,
  * so that a failure on a sparse tmpfs mapping will give SIGBUS not OOM.
  */
@@ -528,7 +528,7 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend,
 
        if (partial_start) {
                struct page *page = NULL;
-               shmem_getpage(inode, start - 1, &page, SGP_READ, NULL);
+               shmem_getpage(inode, start - 1, &page, SGP_READ);
                if (page) {
                        unsigned int top = PAGE_SIZE;
                        if (start > end) {
@@ -543,7 +543,7 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend,
        }
        if (partial_end) {
                struct page *page = NULL;
-               shmem_getpage(inode, end, &page, SGP_READ, NULL);
+               shmem_getpage(inode, end, &page, SGP_READ);
                if (page) {
                        zero_user_segment(page, 0, partial_end);
                        set_page_dirty(page);
@@ -947,8 +947,7 @@ redirty:
        return 0;
 }
 
-#ifdef CONFIG_NUMA
-#ifdef CONFIG_TMPFS
+#if defined(CONFIG_NUMA) && defined(CONFIG_TMPFS)
 static void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol)
 {
        char buffer[64];
@@ -972,7 +971,18 @@ static struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
        }
        return mpol;
 }
-#endif /* CONFIG_TMPFS */
+#else /* !CONFIG_NUMA || !CONFIG_TMPFS */
+static inline void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol)
+{
+}
+static inline struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
+{
+       return NULL;
+}
+#endif /* CONFIG_NUMA && CONFIG_TMPFS */
+#ifndef CONFIG_NUMA
+#define vm_policy vm_private_data
+#endif
 
 static struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp,
                        struct shmem_inode_info *info, pgoff_t index)
@@ -1008,39 +1018,17 @@ static struct page *shmem_alloc_page(gfp_t gfp,
        pvma.vm_ops = NULL;
        pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index);
 
-       page = alloc_page_vma(gfp, &pvma, 0);
+       page = alloc_pages_vma(gfp, 0, &pvma, 0, numa_node_id(), false);
+       if (page) {
+               __SetPageLocked(page);
+               __SetPageSwapBacked(page);
+       }
 
        /* Drop reference taken by mpol_shared_policy_lookup() */
        mpol_cond_put(pvma.vm_policy);
 
        return page;
 }
-#else /* !CONFIG_NUMA */
-#ifdef CONFIG_TMPFS
-static inline void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol)
-{
-}
-#endif /* CONFIG_TMPFS */
-
-static inline struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp,
-                       struct shmem_inode_info *info, pgoff_t index)
-{
-       return swapin_readahead(swap, gfp, NULL, 0);
-}
-
-static inline struct page *shmem_alloc_page(gfp_t gfp,
-                       struct shmem_inode_info *info, pgoff_t index)
-{
-       return alloc_page(gfp);
-}
-#endif /* CONFIG_NUMA */
-
-#if !defined(CONFIG_NUMA) || !defined(CONFIG_TMPFS)
-static inline struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
-{
-       return NULL;
-}
-#endif
 
 /*
  * When a page is moved from swapcache to shmem filecache (either by the
@@ -1084,9 +1072,7 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
        copy_highpage(newpage, oldpage);
        flush_dcache_page(newpage);
 
-       __SetPageLocked(newpage);
        SetPageUptodate(newpage);
-       SetPageSwapBacked(newpage);
        set_page_private(newpage, swap_index);
        SetPageSwapCache(newpage);
 
@@ -1130,14 +1116,19 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
  *
  * If we allocate a new one we do not mark it dirty. That's up to the
  * vm. If we swap it in we mark it dirty since we also free the swap
- * entry since a page cannot live in both the swap and page cache
+ * entry since a page cannot live in both the swap and page cache.
+ *
+ * fault_mm and fault_type are only supplied by shmem_fault:
+ * otherwise they are NULL.
  */
 static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
-       struct page **pagep, enum sgp_type sgp, gfp_t gfp, int *fault_type)
+       struct page **pagep, enum sgp_type sgp, gfp_t gfp,
+       struct mm_struct *fault_mm, int *fault_type)
 {
        struct address_space *mapping = inode->i_mapping;
        struct shmem_inode_info *info;
        struct shmem_sb_info *sbinfo;
+       struct mm_struct *charge_mm;
        struct mem_cgroup *memcg;
        struct page *page;
        swp_entry_t swap;
@@ -1155,7 +1146,7 @@ repeat:
                page = NULL;
        }
 
-       if (sgp != SGP_WRITE && sgp != SGP_FALLOC &&
+       if (sgp <= SGP_CACHE &&
            ((loff_t)index << PAGE_SHIFT) >= i_size_read(inode)) {
                error = -EINVAL;
                goto unlock;
@@ -1183,14 +1174,19 @@ repeat:
         */
        info = SHMEM_I(inode);
        sbinfo = SHMEM_SB(inode->i_sb);
+       charge_mm = fault_mm ? : current->mm;
 
        if (swap.val) {
                /* Look it up and read it in.. */
                page = lookup_swap_cache(swap);
                if (!page) {
-                       /* here we actually do the io */
-                       if (fault_type)
+                       /* Or update major stats only when swapin succeeds?? */
+                       if (fault_type) {
                                *fault_type |= VM_FAULT_MAJOR;
+                               count_vm_event(PGMAJFAULT);
+                               mem_cgroup_count_vm_event(fault_mm, PGMAJFAULT);
+                       }
+                       /* Here we actually start the io */
                        page = shmem_swapin(swap, gfp, info, index);
                        if (!page) {
                                error = -ENOMEM;
@@ -1217,7 +1213,7 @@ repeat:
                                goto failed;
                }
 
-               error = mem_cgroup_try_charge(page, current->mm, gfp, &memcg,
+               error = mem_cgroup_try_charge(page, charge_mm, gfp, &memcg,
                                false);
                if (!error) {
                        error = shmem_add_to_page_cache(page, mapping, index,
@@ -1275,13 +1271,10 @@ repeat:
                        error = -ENOMEM;
                        goto decused;
                }
-
-               __SetPageSwapBacked(page);
-               __SetPageLocked(page);
                if (sgp == SGP_WRITE)
                        __SetPageReferenced(page);
 
-               error = mem_cgroup_try_charge(page, current->mm, gfp, &memcg,
+               error = mem_cgroup_try_charge(page, charge_mm, gfp, &memcg,
                                false);
                if (error)
                        goto decused;
@@ -1321,12 +1314,10 @@ clear:
                        flush_dcache_page(page);
                        SetPageUptodate(page);
                }
-               if (sgp == SGP_DIRTY)
-                       set_page_dirty(page);
        }
 
        /* Perhaps the file has been truncated since we checked */
-       if (sgp != SGP_WRITE && sgp != SGP_FALLOC &&
+       if (sgp <= SGP_CACHE &&
            ((loff_t)index << PAGE_SHIFT) >= i_size_read(inode)) {
                if (alloced) {
                        ClearPageDirty(page);
@@ -1372,6 +1363,7 @@ unlock:
 static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct inode *inode = file_inode(vma->vm_file);
+       gfp_t gfp = mapping_gfp_mask(inode->i_mapping);
        int error;
        int ret = VM_FAULT_LOCKED;
 
@@ -1433,14 +1425,10 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                spin_unlock(&inode->i_lock);
        }
 
-       error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_CACHE, &ret);
+       error = shmem_getpage_gfp(inode, vmf->pgoff, &vmf->page, SGP_CACHE,
+                                 gfp, vma->vm_mm, &ret);
        if (error)
                return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS);
-
-       if (ret & VM_FAULT_MAJOR) {
-               count_vm_event(PGMAJFAULT);
-               mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT);
-       }
        return ret;
 }
 
@@ -1587,7 +1575,7 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
                        return -EPERM;
        }
 
-       return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL);
+       return shmem_getpage(inode, index, pagep, SGP_WRITE);
 }
 
 static int
@@ -1633,7 +1621,7 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
         * and even mark them dirty, so it cannot exceed the max_blocks limit.
         */
        if (!iter_is_iovec(to))
-               sgp = SGP_DIRTY;
+               sgp = SGP_CACHE;
 
        index = *ppos >> PAGE_SHIFT;
        offset = *ppos & ~PAGE_MASK;
@@ -1653,14 +1641,17 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
                                break;
                }
 
-               error = shmem_getpage(inode, index, &page, sgp, NULL);
+               error = shmem_getpage(inode, index, &page, sgp);
                if (error) {
                        if (error == -EINVAL)
                                error = 0;
                        break;
                }
-               if (page)
+               if (page) {
+                       if (sgp == SGP_CACHE)
+                               set_page_dirty(page);
                        unlock_page(page);
+               }
 
                /*
                 * We must evaluate after, since reads (unlike writes)
@@ -1766,7 +1757,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
        error = 0;
 
        while (spd.nr_pages < nr_pages) {
-               error = shmem_getpage(inode, index, &page, SGP_CACHE, NULL);
+               error = shmem_getpage(inode, index, &page, SGP_CACHE);
                if (error)
                        break;
                unlock_page(page);
@@ -1788,8 +1779,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
                page = spd.pages[page_nr];
 
                if (!PageUptodate(page) || page->mapping != mapping) {
-                       error = shmem_getpage(inode, index, &page,
-                                                       SGP_CACHE, NULL);
+                       error = shmem_getpage(inode, index, &page, SGP_CACHE);
                        if (error)
                                break;
                        unlock_page(page);
@@ -2232,8 +2222,7 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
                else if (shmem_falloc.nr_unswapped > shmem_falloc.nr_falloced)
                        error = -ENOMEM;
                else
-                       error = shmem_getpage(inode, index, &page, SGP_FALLOC,
-                                                                       NULL);
+                       error = shmem_getpage(inode, index, &page, SGP_FALLOC);
                if (error) {
                        /* Remove the !PageUptodate pages we added */
                        shmem_undo_range(inode,
@@ -2551,7 +2540,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
                inode->i_op = &shmem_short_symlink_operations;
        } else {
                inode_nohighmem(inode);
-               error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
+               error = shmem_getpage(inode, 0, &page, SGP_WRITE);
                if (error) {
                        iput(inode);
                        return error;
@@ -2592,7 +2581,7 @@ static const char *shmem_get_link(struct dentry *dentry,
                        return ERR_PTR(-ECHILD);
                }
        } else {
-               error = shmem_getpage(inode, 0, &page, SGP_READ, NULL);
+               error = shmem_getpage(inode, 0, &page, SGP_READ);
                if (error)
                        return ERR_PTR(error);
                unlock_page(page);
@@ -2646,20 +2635,21 @@ static int shmem_initxattrs(struct inode *inode,
 }
 
 static int shmem_xattr_handler_get(const struct xattr_handler *handler,
-                                  struct dentry *dentry, const char *name,
-                                  void *buffer, size_t size)
+                                  struct dentry *unused, struct inode *inode,
+                                  const char *name, void *buffer, size_t size)
 {
-       struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
+       struct shmem_inode_info *info = SHMEM_I(inode);
 
        name = xattr_full_name(handler, name);
        return simple_xattr_get(&info->xattrs, name, buffer, size);
 }
 
 static int shmem_xattr_handler_set(const struct xattr_handler *handler,
-                                  struct dentry *dentry, const char *name,
-                                  const void *value, size_t size, int flags)
+                                  struct dentry *unused, struct inode *inode,
+                                  const char *name, const void *value,
+                                  size_t size, int flags)
 {
-       struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
+       struct shmem_inode_info *info = SHMEM_I(inode);
 
        name = xattr_full_name(handler, name);
        return simple_xattr_set(&info->xattrs, name, value, size, flags);
@@ -3123,7 +3113,8 @@ static struct inode *shmem_alloc_inode(struct super_block *sb)
 static void shmem_destroy_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
-       kfree(inode->i_link);
+       if (S_ISLNK(inode->i_mode))
+               kfree(inode->i_link);
        kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
 }
 
@@ -3495,7 +3486,8 @@ struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
        int error;
 
        BUG_ON(mapping->a_ops != &shmem_aops);
-       error = shmem_getpage_gfp(inode, index, &page, SGP_CACHE, gfp, NULL);
+       error = shmem_getpage_gfp(inode, index, &page, SGP_CACHE,
+                                 gfp, NULL, NULL);
        if (error)
                page = ERR_PTR(error);
        else