Commit 8f1dca19 authored by Al Viro's avatar Al Viro Committed by Jan Kara

ext2_rename(): set_link and delete_entry may fail

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Reviewed-by: default avatarFabio M. De Francesco <fmdefrancesco@gmail.com>
Tested-by: default avatarFabio M. De Francesco <fmdefrancesco@gmail.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 6e335cd7
...@@ -606,8 +606,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 *dir, struct page *page, ...@@ -606,8 +606,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 *dir, struct page *page,
if (de->rec_len == 0) { if (de->rec_len == 0) {
ext2_error(inode->i_sb, __func__, ext2_error(inode->i_sb, __func__,
"zero-length directory entry"); "zero-length directory entry");
err = -EIO; return -EIO;
goto out;
} }
pde = de; pde = de;
de = ext2_next_entry(de); de = ext2_next_entry(de);
...@@ -617,7 +616,10 @@ int ext2_delete_entry (struct ext2_dir_entry_2 *dir, struct page *page, ...@@ -617,7 +616,10 @@ int ext2_delete_entry (struct ext2_dir_entry_2 *dir, struct page *page,
pos = page_offset(page) + from; pos = page_offset(page) + from;
lock_page(page); lock_page(page);
err = ext2_prepare_chunk(page, pos, to - from); err = ext2_prepare_chunk(page, pos, to - from);
BUG_ON(err); if (err) {
unlock_page(page);
return err;
}
if (pde) if (pde)
pde->rec_len = ext2_rec_len_to_disk(to - from); pde->rec_len = ext2_rec_len_to_disk(to - from);
dir->inode = 0; dir->inode = 0;
...@@ -625,9 +627,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 *dir, struct page *page, ...@@ -625,9 +627,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 *dir, struct page *page,
inode->i_ctime = inode->i_mtime = current_time(inode); inode->i_ctime = inode->i_mtime = current_time(inode);
EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL; EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL;
mark_inode_dirty(inode); mark_inode_dirty(inode);
err = ext2_handle_dirsync(inode); return ext2_handle_dirsync(inode);
out:
return err;
} }
/* /*
......
...@@ -335,18 +335,16 @@ static int ext2_rename (struct mnt_idmap * idmap, ...@@ -335,18 +335,16 @@ static int ext2_rename (struct mnt_idmap * idmap,
err = dquot_initialize(old_dir); err = dquot_initialize(old_dir);
if (err) if (err)
goto out; return err;
err = dquot_initialize(new_dir); err = dquot_initialize(new_dir);
if (err) if (err)
goto out; return err;
old_de = ext2_find_entry(old_dir, &old_dentry->d_name, &old_page, old_de = ext2_find_entry(old_dir, &old_dentry->d_name, &old_page,
&old_page_addr); &old_page_addr);
if (IS_ERR(old_de)) { if (IS_ERR(old_de))
err = PTR_ERR(old_de); return PTR_ERR(old_de);
goto out;
}
if (S_ISDIR(old_inode->i_mode)) { if (S_ISDIR(old_inode->i_mode)) {
err = -EIO; err = -EIO;
...@@ -394,27 +392,20 @@ static int ext2_rename (struct mnt_idmap * idmap, ...@@ -394,27 +392,20 @@ static int ext2_rename (struct mnt_idmap * idmap,
old_inode->i_ctime = current_time(old_inode); old_inode->i_ctime = current_time(old_inode);
mark_inode_dirty(old_inode); mark_inode_dirty(old_inode);
ext2_delete_entry(old_de, old_page, old_page_addr); err = ext2_delete_entry(old_de, old_page, old_page_addr);
if (!err && dir_de) {
if (dir_de) { if (old_dir != new_dir)
if (old_dir != new_dir) {
err = ext2_set_link(old_inode, dir_de, dir_page, err = ext2_set_link(old_inode, dir_de, dir_page,
dir_page_addr, new_dir, false); dir_page_addr, new_dir, false);
}
ext2_put_page(dir_page, dir_page_addr);
inode_dec_link_count(old_dir); inode_dec_link_count(old_dir);
} }
out_old:
ext2_put_page(old_page, old_page_addr);
out:
return err;
out_dir: out_dir:
if (dir_de) if (dir_de)
ext2_put_page(dir_page, dir_page_addr); ext2_put_page(dir_page, dir_page_addr);
goto out_old; out_old:
ext2_put_page(old_page, old_page_addr);
return err;
} }
const struct inode_operations ext2_dir_inode_operations = { const struct inode_operations ext2_dir_inode_operations = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment