]> Pileus Git - ~andy/linux/blobdiff - mm/shmem.c
ip6tnl/sit: drop packet if ECN present with not-ECT
[~andy/linux] / mm / shmem.c
index d3752110c8c7ee29b7a0d98947366482984c18ca..89341b658bd06b05d908f8becfef7fe0d904b808 100644 (file)
@@ -643,7 +643,7 @@ static void shmem_evict_inode(struct inode *inode)
                kfree(info->symlink);
 
        simple_xattrs_free(&info->xattrs);
-       BUG_ON(inode->i_blocks);
+       WARN_ON(inode->i_blocks);
        shmem_free_inode(inode->i_sb);
        clear_inode(inode);
 }
@@ -1145,8 +1145,20 @@ repeat:
                if (!error) {
                        error = shmem_add_to_page_cache(page, mapping, index,
                                                gfp, swp_to_radix_entry(swap));
-                       /* We already confirmed swap, and make no allocation */
-                       VM_BUG_ON(error);
+                       /*
+                        * We already confirmed swap under page lock, and make
+                        * no memory allocation here, so usually no possibility
+                        * of error; but free_swap_and_cache() only trylocks a
+                        * page, so it is just possible that the entry has been
+                        * truncated or holepunched since swap was confirmed.
+                        * shmem_undo_range() will have done some of the
+                        * unaccounting, now delete_from_swap_cache() will do
+                        * the rest (including mem_cgroup_uncharge_swapcache).
+                        * Reset swap.val? No, leave it so "failed" goes back to
+                        * "repeat": reading a hole and writing should succeed.
+                        */
+                       if (error)
+                               delete_from_swap_cache(page);
                }
                if (error)
                        goto failed;
@@ -1339,7 +1351,6 @@ static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
 {
        file_accessed(file);
        vma->vm_ops = &shmem_vm_ops;
-       vma->vm_flags |= VM_CAN_NONLINEAR;
        return 0;
 }
 
@@ -2221,12 +2232,14 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb,
 {
        struct inode *inode;
        struct dentry *dentry = NULL;
-       u64 inum = fid->raw[2];
-       inum = (inum << 32) | fid->raw[1];
+       u64 inum;
 
        if (fh_len < 3)
                return NULL;
 
+       inum = fid->raw[2];
+       inum = (inum << 32) | fid->raw[1];
+
        inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]),
                        shmem_match, fid->raw);
        if (inode) {
@@ -2643,6 +2656,7 @@ static const struct vm_operations_struct shmem_vm_ops = {
        .set_policy     = shmem_set_policy,
        .get_policy     = shmem_get_policy,
 #endif
+       .remap_pages    = generic_file_remap_pages,
 };
 
 static struct dentry *shmem_mount(struct file_system_type *fs_type,
@@ -2836,7 +2850,6 @@ int shmem_zero_setup(struct vm_area_struct *vma)
                fput(vma->vm_file);
        vma->vm_file = file;
        vma->vm_ops = &shmem_vm_ops;
-       vma->vm_flags |= VM_CAN_NONLINEAR;
        return 0;
 }