Skip to content

Commit 55ce2f6

Browse files
zhangyi089tytso
authored andcommitted
ext4: correct the error path of ext4_write_inline_data_end()
Current error path of ext4_write_inline_data_end() is not correct. Firstly, it should pass out the error value if ext4_get_inode_loc() return fail, or else it could trigger infinite loop if we inject error here. And then it's better to add inode to orphan list if it return fail in ext4_journal_stop(), otherwise we could not restore inline xattr entry after power failure. Finally, we need to reset the 'ret' value if ext4_write_inline_data_end() return success in ext4_write_end() and ext4_journalled_write_end(), otherwise we could not get the error return value of ext4_journal_stop(). Signed-off-by: Zhang Yi <[email protected]> Reviewed-by: Jan Kara <[email protected]> Signed-off-by: Theodore Ts'o <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 4df031f commit 55ce2f6

File tree

2 files changed

+10
-12
lines changed

2 files changed

+10
-12
lines changed

fs/ext4/inline.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -733,25 +733,20 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
733733
void *kaddr;
734734
struct ext4_iloc iloc;
735735

736-
if (unlikely(copied < len)) {
737-
if (!PageUptodate(page)) {
738-
copied = 0;
739-
goto out;
740-
}
741-
}
736+
if (unlikely(copied < len) && !PageUptodate(page))
737+
return 0;
742738

743739
ret = ext4_get_inode_loc(inode, &iloc);
744740
if (ret) {
745741
ext4_std_error(inode->i_sb, ret);
746-
copied = 0;
747-
goto out;
742+
return ret;
748743
}
749744

750745
ext4_write_lock_xattr(inode, &no_expand);
751746
BUG_ON(!ext4_has_inline_data(inode));
752747

753748
kaddr = kmap_atomic(page);
754-
ext4_write_inline_data(inode, &iloc, kaddr, pos, len);
749+
ext4_write_inline_data(inode, &iloc, kaddr, pos, copied);
755750
kunmap_atomic(kaddr);
756751
SetPageUptodate(page);
757752
/* clear page dirty so that writepages wouldn't work for us. */
@@ -760,7 +755,7 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
760755
ext4_write_unlock_xattr(inode, &no_expand);
761756
brelse(iloc.bh);
762757
mark_inode_dirty(inode);
763-
out:
758+
764759
return copied;
765760
}
766761

fs/ext4/inode.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,7 @@ static int ext4_write_end(struct file *file,
12951295
goto errout;
12961296
}
12971297
copied = ret;
1298+
ret = 0;
12981299
} else
12991300
copied = block_write_end(file, mapping, pos,
13001301
len, copied, page, fsdata);
@@ -1321,13 +1322,14 @@ static int ext4_write_end(struct file *file,
13211322
if (i_size_changed || inline_data)
13221323
ret = ext4_mark_inode_dirty(handle, inode);
13231324

1325+
errout:
13241326
if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode))
13251327
/* if we have allocated more blocks and copied
13261328
* less. We will have blocks allocated outside
13271329
* inode->i_size. So truncate them
13281330
*/
13291331
ext4_orphan_add(handle, inode);
1330-
errout:
1332+
13311333
ret2 = ext4_journal_stop(handle);
13321334
if (!ret)
13331335
ret = ret2;
@@ -1410,6 +1412,7 @@ static int ext4_journalled_write_end(struct file *file,
14101412
goto errout;
14111413
}
14121414
copied = ret;
1415+
ret = 0;
14131416
} else if (unlikely(copied < len) && !PageUptodate(page)) {
14141417
copied = 0;
14151418
ext4_journalled_zero_new_buffers(handle, page, from, to);
@@ -1439,14 +1442,14 @@ static int ext4_journalled_write_end(struct file *file,
14391442
ret = ret2;
14401443
}
14411444

1445+
errout:
14421446
if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode))
14431447
/* if we have allocated more blocks and copied
14441448
* less. We will have blocks allocated outside
14451449
* inode->i_size. So truncate them
14461450
*/
14471451
ext4_orphan_add(handle, inode);
14481452

1449-
errout:
14501453
ret2 = ext4_journal_stop(handle);
14511454
if (!ret)
14521455
ret = ret2;

0 commit comments

Comments
 (0)