diff options
author | Namhyung Kim <namhyung@gmail.com> | 2011-01-10 12:11:16 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-01-10 12:11:16 -0500 |
commit | dabd991f9d8e3232bb4531c920daddac8d10d313 (patch) | |
tree | f914ebaba1b4fe686260e4a6479d2050ff2cbdb2 | |
parent | f1dffc4c5431c6bd8972489636573c5cd09ab672 (diff) |
ext4: add more error checks to ext4_mkdir()
Check return value of ext4_journal_get_write_access,
ext4_journal_dirty_metadata and ext4_mark_inode_dirty. Move brelse()
under 'out_stop' to release bh properly in case of journal error.
Signed-off-by: Namhyung Kim <namhyung@gmail.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r-- | fs/ext4/namei.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 96a594d86a19..6dfc5b9de3e6 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -1789,7 +1789,7 @@ static int ext4_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
1789 | { | 1789 | { |
1790 | handle_t *handle; | 1790 | handle_t *handle; |
1791 | struct inode *inode; | 1791 | struct inode *inode; |
1792 | struct buffer_head *dir_block; | 1792 | struct buffer_head *dir_block = NULL; |
1793 | struct ext4_dir_entry_2 *de; | 1793 | struct ext4_dir_entry_2 *de; |
1794 | unsigned int blocksize = dir->i_sb->s_blocksize; | 1794 | unsigned int blocksize = dir->i_sb->s_blocksize; |
1795 | int err, retries = 0; | 1795 | int err, retries = 0; |
@@ -1822,7 +1822,9 @@ retry: | |||
1822 | if (!dir_block) | 1822 | if (!dir_block) |
1823 | goto out_clear_inode; | 1823 | goto out_clear_inode; |
1824 | BUFFER_TRACE(dir_block, "get_write_access"); | 1824 | BUFFER_TRACE(dir_block, "get_write_access"); |
1825 | ext4_journal_get_write_access(handle, dir_block); | 1825 | err = ext4_journal_get_write_access(handle, dir_block); |
1826 | if (err) | ||
1827 | goto out_clear_inode; | ||
1826 | de = (struct ext4_dir_entry_2 *) dir_block->b_data; | 1828 | de = (struct ext4_dir_entry_2 *) dir_block->b_data; |
1827 | de->inode = cpu_to_le32(inode->i_ino); | 1829 | de->inode = cpu_to_le32(inode->i_ino); |
1828 | de->name_len = 1; | 1830 | de->name_len = 1; |
@@ -1839,10 +1841,12 @@ retry: | |||
1839 | ext4_set_de_type(dir->i_sb, de, S_IFDIR); | 1841 | ext4_set_de_type(dir->i_sb, de, S_IFDIR); |
1840 | inode->i_nlink = 2; | 1842 | inode->i_nlink = 2; |
1841 | BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata"); | 1843 | BUFFER_TRACE(dir_block, "call ext4_handle_dirty_metadata"); |
1842 | ext4_handle_dirty_metadata(handle, dir, dir_block); | 1844 | err = ext4_handle_dirty_metadata(handle, dir, dir_block); |
1843 | brelse(dir_block); | 1845 | if (err) |
1844 | ext4_mark_inode_dirty(handle, inode); | 1846 | goto out_clear_inode; |
1845 | err = ext4_add_entry(handle, dentry, inode); | 1847 | err = ext4_mark_inode_dirty(handle, inode); |
1848 | if (!err) | ||
1849 | err = ext4_add_entry(handle, dentry, inode); | ||
1846 | if (err) { | 1850 | if (err) { |
1847 | out_clear_inode: | 1851 | out_clear_inode: |
1848 | clear_nlink(inode); | 1852 | clear_nlink(inode); |
@@ -1853,10 +1857,13 @@ out_clear_inode: | |||
1853 | } | 1857 | } |
1854 | ext4_inc_count(handle, dir); | 1858 | ext4_inc_count(handle, dir); |
1855 | ext4_update_dx_flag(dir); | 1859 | ext4_update_dx_flag(dir); |
1856 | ext4_mark_inode_dirty(handle, dir); | 1860 | err = ext4_mark_inode_dirty(handle, dir); |
1861 | if (err) | ||
1862 | goto out_clear_inode; | ||
1857 | d_instantiate(dentry, inode); | 1863 | d_instantiate(dentry, inode); |
1858 | unlock_new_inode(inode); | 1864 | unlock_new_inode(inode); |
1859 | out_stop: | 1865 | out_stop: |
1866 | brelse(dir_block); | ||
1860 | ext4_journal_stop(handle); | 1867 | ext4_journal_stop(handle); |
1861 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) | 1868 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
1862 | goto retry; | 1869 | goto retry; |