add patch fix-fencepost-in-s_first_meta_bg-validation
[ext4-patch-queue.git] / fix-write_inline_data_end-handling
blob53a2b0d8356cd7bd3b2b5a9be0879b9a043555c3
1 ext4: fix inline data error paths
3 The write_end() function must always unlock the page and drop its ref
4 count, even on an error.
6 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
7 Cc: stable@vger.kernel.org
8 ---
9  fs/ext4/inline.c |  9 ++++++++-
10  fs/ext4/inode.c  | 20 +++++++++++++++-----
11  2 files changed, 23 insertions(+), 6 deletions(-)
13 diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
14 index 338cfd862adb..b777b8aa14ae 100644
15 --- a/fs/ext4/inline.c
16 +++ b/fs/ext4/inline.c
17 @@ -943,8 +943,15 @@ int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
18                                   struct page *page)
19  {
20         int i_size_changed = 0;
21 +       int ret;
23 -       copied = ext4_write_inline_data_end(inode, pos, len, copied, page);
24 +       ret = ext4_write_inline_data_end(inode, pos, len, copied, page);
25 +       if (ret < 0) {
26 +               unlock_page(page);
27 +               put_page(page);
28 +               return ret;
29 +       }
30 +       copied = ret;
32         /*
33          * No need to use i_size_read() here, the i_size
34 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
35 index 918d351d5b94..af97b9170358 100644
36 --- a/fs/ext4/inode.c
37 +++ b/fs/ext4/inode.c
38 @@ -1330,8 +1330,11 @@ static int ext4_write_end(struct file *file,
39         if (ext4_has_inline_data(inode)) {
40                 ret = ext4_write_inline_data_end(inode, pos, len,
41                                                  copied, page);
42 -               if (ret < 0)
43 +               if (ret < 0) {
44 +                       unlock_page(page);
45 +                       put_page(page);
46                         goto errout;
47 +               }
48                 copied = ret;
49         } else
50                 copied = block_write_end(file, mapping, pos,
51 @@ -1433,10 +1436,16 @@ static int ext4_journalled_write_end(struct file *file,
53         BUG_ON(!ext4_handle_valid(handle));
55 -       if (ext4_has_inline_data(inode))
56 -               copied = ext4_write_inline_data_end(inode, pos, len,
57 -                                                   copied, page);
58 -       else if (unlikely(copied < len) && !PageUptodate(page)) {
59 +       if (ext4_has_inline_data(inode)) {
60 +               ret = ext4_write_inline_data_end(inode, pos, len,
61 +                                                copied, page);
62 +               if (ret < 0) {
63 +                       unlock_page(page);
64 +                       put_page(page);
65 +                       goto errout;
66 +               }
67 +               copied = ret;
68 +       } else if (unlikely(copied < len) && !PageUptodate(page)) {
69                 copied = 0;
70                 ext4_journalled_zero_new_buffers(handle, page, from, to);
71         } else {
72 @@ -1471,6 +1480,7 @@ static int ext4_journalled_write_end(struct file *file,
73                  */
74                 ext4_orphan_add(handle, inode);
76 +errout:
77         ret2 = ext4_journal_stop(handle);
78         if (!ret)
79                 ret = ret2;