Merge tag 'v3.10.103' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / mm / shmem.c
index cc02b6c6eec486a2cd6d816fc0313b89771637ae..d95e308fc4aae57d04959613c8ed479fc73d351e 100644 (file)
@@ -848,7 +848,11 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
                SetPageUptodate(page);
        }
 
+#ifndef CONFIG_MEMCG
        swap = get_swap_page();
+#else
+       swap = get_swap_page_by_memcg(page);
+#endif
        if (!swap.val)
                goto redirty;
 
@@ -1428,7 +1432,7 @@ static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
 }
 
 static struct inode *shmem_get_inode(struct super_block *sb, const struct inode *dir,
-                                    umode_t mode, dev_t dev, unsigned long flags)
+                                    umode_t mode, dev_t dev, unsigned long flags, int atomic_copy)
 {
        struct inode *inode;
        struct shmem_inode_info *info;
@@ -1439,6 +1443,8 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
 
        inode = new_inode(sb);
        if (inode) {
+               /* We don't let shmem use __GFP_SLOWHIGHMEM */
+               mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER_MOVABLE);
                inode->i_ino = get_next_ino();
                inode_init_owner(inode, dir, mode);
                inode->i_blocks = 0;
@@ -1449,6 +1455,8 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
                memset(info, 0, (char *)inode - (char *)info);
                spin_lock_init(&info->lock);
                info->flags = flags & VM_NORESERVE;
+               if (atomic_copy)
+                       inode->i_flags |= S_ATOMIC_COPY;
                INIT_LIST_HEAD(&info->swaplist);
                simple_xattrs_init(&info->xattrs);
                cache_no_acl(inode);
@@ -1881,7 +1889,9 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
        pgoff_t start, index, end;
        int error;
 
-       mutex_lock(&inode->i_mutex);
+       //To avoid nested lock
+       if (!mutex_trylock(&inode->i_mutex))
+               return -1;
 
        if (mode & FALLOC_FL_PUNCH_HOLE) {
                struct address_space *mapping = file->f_mapping;
@@ -2019,7 +2029,7 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
        struct inode *inode;
        int error = -ENOSPC;
 
-       inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE);
+       inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE, 0);
        if (inode) {
                error = security_inode_init_security(inode, dir,
                                                     &dentry->d_name,
@@ -2160,7 +2170,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
        if (len > PAGE_CACHE_SIZE)
                return -ENAMETOOLONG;
 
-       inode = shmem_get_inode(dir->i_sb, dir, S_IFLNK|S_IRWXUGO, 0, VM_NORESERVE);
+       inode = shmem_get_inode(dir->i_sb, dir, S_IFLNK|S_IRWXUGO, 0, VM_NORESERVE, 0);
        if (!inode)
                return -ENOSPC;
 
@@ -2702,7 +2712,7 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_flags |= MS_POSIXACL;
 #endif
 
-       inode = shmem_get_inode(sb, NULL, S_IFDIR | sbinfo->mode, 0, VM_NORESERVE);
+       inode = shmem_get_inode(sb, NULL, S_IFDIR | sbinfo->mode, 0, VM_NORESERVE, 0);
        if (!inode)
                goto failed;
        inode->i_uid = sbinfo->uid;
@@ -2955,7 +2965,7 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
 
 #define shmem_vm_ops                           generic_file_vm_ops
 #define shmem_file_operations                  ramfs_file_operations
-#define shmem_get_inode(sb, dir, mode, dev, flags)     ramfs_get_inode(sb, dir, mode, dev)
+#define shmem_get_inode(sb, dir, mode, dev, flags, atomic_copy)        ramfs_get_inode(sb, dir, mode, dev)
 #define shmem_acct_size(flags, size)           0
 #define shmem_unacct_size(flags, size)         do {} while (0)
 
@@ -2972,8 +2982,10 @@ static struct dentry_operations anon_ops = {
  * @name: name for dentry (to be seen in /proc/<pid>/maps
  * @size: size to be set for the file
  * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
+ * @atomic_copy: Atomically copy the area when hibernating?
  */
-struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
+struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags,
+               int atomic_copy)
 {
        struct file *res;
        struct inode *inode;
@@ -3002,7 +3014,7 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags
        path.mnt = mntget(shm_mnt);
 
        res = ERR_PTR(-ENOSPC);
-       inode = shmem_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0, flags);
+       inode = shmem_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0, flags, atomic_copy);
        if (!inode)
                goto put_dentry;
 
@@ -3028,6 +3040,14 @@ put_memory:
 }
 EXPORT_SYMBOL_GPL(shmem_file_setup);
 
+void shmem_set_file(struct vm_area_struct *vma, struct file *file)
+{
+       if (vma->vm_file)
+               fput(vma->vm_file);
+       vma->vm_file = file;
+       vma->vm_ops = &shmem_vm_ops;
+}
+
 /**
  * shmem_zero_setup - setup a shared anonymous mapping
  * @vma: the vma to be mmapped is prepared by do_mmap_pgoff
@@ -3037,14 +3057,11 @@ int shmem_zero_setup(struct vm_area_struct *vma)
        struct file *file;
        loff_t size = vma->vm_end - vma->vm_start;
 
-       file = shmem_file_setup("dev/zero", size, vma->vm_flags);
+       file = shmem_file_setup("dev/zero", size, vma->vm_flags, 0);
        if (IS_ERR(file))
                return PTR_ERR(file);
 
-       if (vma->vm_file)
-               fput(vma->vm_file);
-       vma->vm_file = file;
-       vma->vm_ops = &shmem_vm_ops;
+       shmem_set_file(vma, file);
        return 0;
 }