]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
ext4: fix inline data error paths
authorTheodore Ts'o <tytso@mit.edu>
Sun, 5 Feb 2017 04:04:00 +0000 (23:04 -0500)
committerTim Gardner <tim.gardner@canonical.com>
Mon, 13 Mar 2017 21:20:54 +0000 (15:20 -0600)
BugLink: http://bugs.launchpad.net/bugs/1672544
commit eb5efbcb762aee4b454b04f7115f73ccbcf8f0ef upstream.

The write_end() function must always unlock the page and drop its ref
count, even on an error.

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
fs/ext4/inline.c
fs/ext4/inode.c

index 99a5312ced5205e05d35b72fc27a23bab546cc94..627ace3447397ff36c1bb3efd5874320763979ea 100644 (file)
@@ -943,8 +943,15 @@ int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
                                  struct page *page)
 {
        int i_size_changed = 0;
+       int ret;
 
-       copied = ext4_write_inline_data_end(inode, pos, len, copied, page);
+       ret = ext4_write_inline_data_end(inode, pos, len, copied, page);
+       if (ret < 0) {
+               unlock_page(page);
+               put_page(page);
+               return ret;
+       }
+       copied = ret;
 
        /*
         * No need to use i_size_read() here, the i_size
index 6682eda10bfc58998d6606e73021ff4cb5d9cc93..3648060705b3f4252258004f88992f1e32832dd5 100644 (file)
@@ -1330,8 +1330,11 @@ static int ext4_write_end(struct file *file,
        if (ext4_has_inline_data(inode)) {
                ret = ext4_write_inline_data_end(inode, pos, len,
                                                 copied, page);
-               if (ret < 0)
+               if (ret < 0) {
+                       unlock_page(page);
+                       put_page(page);
                        goto errout;
+               }
                copied = ret;
        } else
                copied = block_write_end(file, mapping, pos,
@@ -1433,10 +1436,16 @@ static int ext4_journalled_write_end(struct file *file,
 
        BUG_ON(!ext4_handle_valid(handle));
 
-       if (ext4_has_inline_data(inode))
-               copied = ext4_write_inline_data_end(inode, pos, len,
-                                                   copied, page);
-       else if (unlikely(copied < len) && !PageUptodate(page)) {
+       if (ext4_has_inline_data(inode)) {
+               ret = ext4_write_inline_data_end(inode, pos, len,
+                                                copied, page);
+               if (ret < 0) {
+                       unlock_page(page);
+                       put_page(page);
+                       goto errout;
+               }
+               copied = ret;
+       } else if (unlikely(copied < len) && !PageUptodate(page)) {
                copied = 0;
                ext4_journalled_zero_new_buffers(handle, page, from, to);
        } else {
@@ -1471,6 +1480,7 @@ static int ext4_journalled_write_end(struct file *file,
                 */
                ext4_orphan_add(handle, inode);
 
+errout:
        ret2 = ext4_journal_stop(handle);
        if (!ret)
                ret = ret2;