add patch fix-reservation-release-on-invalidatepage-for-delalloc-fs
[ext4-patch-queue.git] / fix-reservation-release-on-invalidatepage-for-delalloc-fs
blob59564bb4b24eaeae5e1cb408942f7afefd2ab25f
1 ext4: fix reservation release on invalidatepage for delalloc fs
3 From: Lukas Czerner <lczerner@redhat.com>
5 On delalloc enabled file system on invalidatepage operation
6 in ext4_da_page_release_reservation() we want to clear the delayed
7 buffer and remove the extent covering the delayed buffer from the extent
8 status tree.
10 However currently there is a bug where on the systems with page size >
11 block size we will always remove extents from the start of the page
12 regardless where the actual delayed buffers are positioned in the page.
13 This leads to the errors like this:
15 EXT4-fs warning (device loop0): ext4_da_release_space:1225:
16 ext4_da_release_space: ino 13, to_free 1 with only 0 reserved data
17 blocks
19 This however can cause data loss on writeback time if the file system is
20 in ENOSPC condition because we're releasing reservation for someones
21 else delayed buffer.
23 Fix this by only removing extents that corresponds to the part of the
24 page we want to invalidate.
26 This problem is reproducible by the following fio receipt (however I was
27 only able to reproduce it with fio-2.1 or older.
29 [global]
30 bs=8k
31 iodepth=1024
32 iodepth_batch=60
33 randrepeat=1
34 size=1m
35 directory=/mnt/test
36 numjobs=20
37 [job1]
38 ioengine=sync
39 bs=1k
40 direct=1
41 rw=randread
42 filename=file1:file2
43 [job2]
44 ioengine=libaio
45 rw=randwrite
46 direct=1
47 filename=file1:file2
48 [job3]
49 bs=1k
50 ioengine=posixaio
51 rw=randwrite
52 direct=1
53 filename=file1:file2
54 [job5]
55 bs=1k
56 ioengine=sync
57 rw=randread
58 filename=file1:file2
59 [job7]
60 ioengine=libaio
61 rw=randwrite
62 filename=file1:file2
63 [job8]
64 ioengine=posixaio
65 rw=randwrite
66 filename=file1:file2
67 [job10]
68 ioengine=mmap
69 rw=randwrite
70 bs=1k
71 filename=file1:file2
72 [job11]
73 ioengine=mmap
74 rw=randwrite
75 direct=1
76 filename=file1:file2
78 Signed-off-by: Lukas Czerner <lczerner@redhat.com>
79 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
80 Reviewed-by: Jan Kara <jack@suse.cz>
81 Cc: stable@vger.kernel.org
82 ---
83  fs/ext4/inode.c | 15 ++++++++++++---
84  1 file changed, 12 insertions(+), 3 deletions(-)
86 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
87 index 0554b0b..46f4a49 100644
88 --- a/fs/ext4/inode.c
89 +++ b/fs/ext4/inode.c
90 @@ -1342,7 +1342,7 @@ static void ext4_da_page_release_reservation(struct page *page,
91                                              unsigned int offset,
92                                              unsigned int length)
93  {
94 -       int to_release = 0;
95 +       int to_release = 0, contiguous_blks = 0;
96         struct buffer_head *head, *bh;
97         unsigned int curr_off = 0;
98         struct inode *inode = page->mapping->host;
99 @@ -1363,14 +1363,23 @@ static void ext4_da_page_release_reservation(struct page *page,
101                 if ((offset <= curr_off) && (buffer_delay(bh))) {
102                         to_release++;
103 +                       contiguous_blks++;
104                         clear_buffer_delay(bh);
105 +               } else if (contiguous_blks) {
106 +                       lblk = page->index <<
107 +                              (PAGE_CACHE_SHIFT - inode->i_blkbits);
108 +                       lblk += (curr_off >> inode->i_blkbits) -
109 +                               contiguous_blks;
110 +                       ext4_es_remove_extent(inode, lblk, contiguous_blks);
111 +                       contiguous_blks = 0;
112                 }
113                 curr_off = next_off;
114         } while ((bh = bh->b_this_page) != head);
116 -       if (to_release) {
117 +       if (contiguous_blks) {
118                 lblk = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
119 -               ext4_es_remove_extent(inode, lblk, to_release);
120 +               lblk += (curr_off >> inode->i_blkbits) - contiguous_blks;
121 +               ext4_es_remove_extent(inode, lblk, contiguous_blks);
122         }
124         /* If we have released all the blocks belonging to a cluster, then we
125 -- 
126 1.8.3.1
129 To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
130 the body of a message to majordomo@vger.kernel.org
131 More majordomo info at  http://vger.kernel.org/majordomo-info.html