add patch preload-block-group-descriptors
[ext4-patch-queue.git] / evict-inline-data-when-writing-to-memory-map
blob4e013f7faa4bc739cb41aac84915a187914476af
1 ext4: evict inline data when writing to memory map
3 From: Eric Biggers <ebiggers@google.com>
5 Currently the case of writing via mmap to a file with inline data is not
6 handled.  This is maybe a rare case since it requires a writable memory
7 map of a very small file, but it is trivial to trigger with on
8 inline_data filesystem, and it causes the
9 'BUG_ON(ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA));' in
10 ext4_writepages() to be hit:
12     mkfs.ext4 -O inline_data /dev/vdb
13     mount /dev/vdb /mnt
14     xfs_io -f /mnt/file \
15         -c 'pwrite 0 1' \
16         -c 'mmap -w 0 1m' \
17         -c 'mwrite 0 1' \
18         -c 'fsync'
20         kernel BUG at fs/ext4/inode.c:2723!
21         invalid opcode: 0000 [#1] SMP
22         CPU: 1 PID: 2532 Comm: xfs_io Not tainted 4.11.0-rc1-xfstests-00301-g071d9acf3d1f #633
23         Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-20170228_101828-anatol 04/01/2014
24         task: ffff88003d3a8040 task.stack: ffffc90000300000
25         RIP: 0010:ext4_writepages+0xc89/0xf8a
26         RSP: 0018:ffffc90000303ca0 EFLAGS: 00010283
27         RAX: 0000028410000000 RBX: ffff8800383fa3b0 RCX: ffffffff812afcdc
28         RDX: 00000a9d00000246 RSI: ffffffff81e660e0 RDI: 0000000000000246
29         RBP: ffffc90000303dc0 R08: 0000000000000002 R09: 869618e8f99b4fa5
30         R10: 00000000852287a2 R11: 00000000a03b49f4 R12: ffff88003808e698
31         R13: 0000000000000000 R14: 7fffffffffffffff R15: 7fffffffffffffff
32         FS:  00007fd3e53094c0(0000) GS:ffff88003e400000(0000) knlGS:0000000000000000
33         CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
34         CR2: 00007fd3e4c51000 CR3: 000000003d554000 CR4: 00000000003406e0
35         Call Trace:
36          ? _raw_spin_unlock+0x27/0x2a
37          ? kvm_clock_read+0x1e/0x20
38          do_writepages+0x23/0x2c
39          ? do_writepages+0x23/0x2c
40          __filemap_fdatawrite_range+0x80/0x87
41          filemap_write_and_wait_range+0x67/0x8c
42          ext4_sync_file+0x20e/0x472
43          vfs_fsync_range+0x8e/0x9f
44          ? syscall_trace_enter+0x25b/0x2d0
45          vfs_fsync+0x1c/0x1e
46          do_fsync+0x31/0x4a
47          SyS_fsync+0x10/0x14
48          do_syscall_64+0x69/0x131
49          entry_SYSCALL64_slow_path+0x25/0x25
51 We could try to be smart and keep the inline data in this case, or at
52 least support delayed allocation when allocating the block, but these
53 solutions would be more complicated and don't seem worthwhile given how
54 rare this case seems to be.  So just fix the bug by calling
55 ext4_convert_inline_data() when we're asked to make a page writable, so
56 that any inline data gets evicted, with the block allocated immediately.
58 Reported-by: Nick Alcock <nick.alcock@oracle.com>
59 Cc: stable@vger.kernel.org
60 Reviewed-by: Andreas Dilger <adilger@dilger.ca>
61 Signed-off-by: Eric Biggers <ebiggers@google.com>
62 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
63 ---
64  fs/ext4/inode.c | 5 +++++
65  1 file changed, 5 insertions(+)
67 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
68 index 7385e6a6b6cb..0fc3e25ef531 100644
69 --- a/fs/ext4/inode.c
70 +++ b/fs/ext4/inode.c
71 @@ -5839,6 +5839,11 @@ int ext4_page_mkwrite(struct vm_fault *vmf)
72         file_update_time(vma->vm_file);
74         down_read(&EXT4_I(inode)->i_mmap_sem);
76 +       ret = ext4_convert_inline_data(inode);
77 +       if (ret)
78 +               goto out_ret;
80         /* Delalloc case is easy... */
81         if (test_opt(inode->i_sb, DELALLOC) &&
82             !ext4_should_journal_data(inode) &&
83 -- 
84 2.12.0