aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2017-02-04 23:04:00 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-12 00:41:46 -0500
commit0b37d0c0c6b35317bfc3aee8cdf94f853d594e5f (patch)
tree5624710ad17e61535ed48e2fffa85eb4e007a72c /fs
parent68ca0fdac41fa801e1e6c2f99e27a9c24e494532 (diff)
ext4: fix inline data error paths
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/inline.c9
-rw-r--r--fs/ext4/inode.c20
2 files changed, 23 insertions, 6 deletions
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index 028329721bbe..37b521ed39df 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -933,8 +933,15 @@ int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos,
933 struct page *page) 933 struct page *page)
934{ 934{
935 int i_size_changed = 0; 935 int i_size_changed = 0;
936 int ret;
936 937
937 copied = ext4_write_inline_data_end(inode, pos, len, copied, page); 938 ret = ext4_write_inline_data_end(inode, pos, len, copied, page);
939 if (ret < 0) {
940 unlock_page(page);
941 put_page(page);
942 return ret;
943 }
944 copied = ret;
938 945
939 /* 946 /*
940 * No need to use i_size_read() here, the i_size 947 * No need to use i_size_read() here, the i_size
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index a48b17cc0cd1..1d4f5faa04b5 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1324,8 +1324,11 @@ static int ext4_write_end(struct file *file,
1324 if (ext4_has_inline_data(inode)) { 1324 if (ext4_has_inline_data(inode)) {
1325 ret = ext4_write_inline_data_end(inode, pos, len, 1325 ret = ext4_write_inline_data_end(inode, pos, len,
1326 copied, page); 1326 copied, page);
1327 if (ret < 0) 1327 if (ret < 0) {
1328 unlock_page(page);
1329 put_page(page);
1328 goto errout; 1330 goto errout;
1331 }
1329 copied = ret; 1332 copied = ret;
1330 } else 1333 } else
1331 copied = block_write_end(file, mapping, pos, 1334 copied = block_write_end(file, mapping, pos,
@@ -1427,10 +1430,16 @@ static int ext4_journalled_write_end(struct file *file,
1427 1430
1428 BUG_ON(!ext4_handle_valid(handle)); 1431 BUG_ON(!ext4_handle_valid(handle));
1429 1432
1430 if (ext4_has_inline_data(inode)) 1433 if (ext4_has_inline_data(inode)) {
1431 copied = ext4_write_inline_data_end(inode, pos, len, 1434 ret = ext4_write_inline_data_end(inode, pos, len,
1432 copied, page); 1435 copied, page);
1433 else if (unlikely(copied < len) && !PageUptodate(page)) { 1436 if (ret < 0) {
1437 unlock_page(page);
1438 put_page(page);
1439 goto errout;
1440 }
1441 copied = ret;
1442 } else if (unlikely(copied < len) && !PageUptodate(page)) {
1434 copied = 0; 1443 copied = 0;
1435 ext4_journalled_zero_new_buffers(handle, page, from, to); 1444 ext4_journalled_zero_new_buffers(handle, page, from, to);
1436 } else { 1445 } else {
@@ -1465,6 +1474,7 @@ static int ext4_journalled_write_end(struct file *file,
1465 */ 1474 */
1466 ext4_orphan_add(handle, inode); 1475 ext4_orphan_add(handle, inode);
1467 1476
1477errout:
1468 ret2 = ext4_journal_stop(handle); 1478 ret2 = ext4_journal_stop(handle);
1469 if (!ret) 1479 if (!ret)
1470 ret = ret2; 1480 ret = ret2;