diff options
author | Jan Kara <jack@suse.cz> | 2014-10-30 10:53:17 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2014-10-30 10:53:17 -0400 |
commit | 6050d47adcadbb53582434d919ed7f038d936712 (patch) | |
tree | 25fdc7507203649d82fdd1c943b1e70ac2cb6722 /fs | |
parent | d48458d4a768cece43f80a081a26cf912877da9c (diff) |
ext4: bail out from make_indexed_dir() on first error
When ext4_handle_dirty_dx_node() or ext4_handle_dirty_dirent_node()
fail, there's really something wrong with the fs and there's no point in
continuing further. Just return error from make_indexed_dir() in that
case. Also initialize frames array so that if we return early due to
error, dx_release() doesn't try to dereference uninitialized memory
(which could happen also due to error in do_split()).
Coverity-id: 741300
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@vger.kernel.org
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/namei.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 123798c5ac31..426211882f72 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -1816,31 +1816,39 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1816 | hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; | 1816 | hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; |
1817 | hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; | 1817 | hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; |
1818 | ext4fs_dirhash(name, namelen, &hinfo); | 1818 | ext4fs_dirhash(name, namelen, &hinfo); |
1819 | memset(frames, 0, sizeof(frames)); | ||
1819 | frame = frames; | 1820 | frame = frames; |
1820 | frame->entries = entries; | 1821 | frame->entries = entries; |
1821 | frame->at = entries; | 1822 | frame->at = entries; |
1822 | frame->bh = bh; | 1823 | frame->bh = bh; |
1823 | bh = bh2; | 1824 | bh = bh2; |
1824 | 1825 | ||
1825 | ext4_handle_dirty_dx_node(handle, dir, frame->bh); | 1826 | retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh); |
1826 | ext4_handle_dirty_dirent_node(handle, dir, bh); | 1827 | if (retval) |
1828 | goto out_frames; | ||
1829 | retval = ext4_handle_dirty_dirent_node(handle, dir, bh); | ||
1830 | if (retval) | ||
1831 | goto out_frames; | ||
1827 | 1832 | ||
1828 | de = do_split(handle,dir, &bh, frame, &hinfo); | 1833 | de = do_split(handle,dir, &bh, frame, &hinfo); |
1829 | if (IS_ERR(de)) { | 1834 | if (IS_ERR(de)) { |
1830 | /* | 1835 | retval = PTR_ERR(de); |
1831 | * Even if the block split failed, we have to properly write | 1836 | goto out_frames; |
1832 | * out all the changes we did so far. Otherwise we can end up | ||
1833 | * with corrupted filesystem. | ||
1834 | */ | ||
1835 | ext4_mark_inode_dirty(handle, dir); | ||
1836 | dx_release(frames); | ||
1837 | return PTR_ERR(de); | ||
1838 | } | 1837 | } |
1839 | dx_release(frames); | 1838 | dx_release(frames); |
1840 | 1839 | ||
1841 | retval = add_dirent_to_buf(handle, dentry, inode, de, bh); | 1840 | retval = add_dirent_to_buf(handle, dentry, inode, de, bh); |
1842 | brelse(bh); | 1841 | brelse(bh); |
1843 | return retval; | 1842 | return retval; |
1843 | out_frames: | ||
1844 | /* | ||
1845 | * Even if the block split failed, we have to properly write | ||
1846 | * out all the changes we did so far. Otherwise we can end up | ||
1847 | * with corrupted filesystem. | ||
1848 | */ | ||
1849 | ext4_mark_inode_dirty(handle, dir); | ||
1850 | dx_release(frames); | ||
1851 | return retval; | ||
1844 | } | 1852 | } |
1845 | 1853 | ||
1846 | /* | 1854 | /* |