OSDN Git Service

ext2_rename(): set_link and delete_entry may fail
authorAl Viro <viro@zeniv.linux.org.uk>
Wed, 11 Jan 2023 20:21:52 +0000 (15:21 -0500)
committerJan Kara <jack@suse.cz>
Mon, 29 May 2023 09:03:06 +0000 (11:03 +0200)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Reviewed-by: Fabio M. De Francesco <fmdefrancesco@gmail.com>
Tested-by: Fabio M. De Francesco <fmdefrancesco@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
fs/ext2/dir.c
fs/ext2/namei.c

index 4a6955a..a3c77ea 100644 (file)
@@ -606,8 +606,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 *dir, struct page *page,
                if (de->rec_len == 0) {
                        ext2_error(inode->i_sb, __func__,
                                "zero-length directory entry");
-                       err = -EIO;
-                       goto out;
+                       return -EIO;
                }
                pde = de;
                de = ext2_next_entry(de);
@@ -617,7 +616,10 @@ int ext2_delete_entry (struct ext2_dir_entry_2 *dir, struct page *page,
        pos = page_offset(page) + from;
        lock_page(page);
        err = ext2_prepare_chunk(page, pos, to - from);
-       BUG_ON(err);
+       if (err) {
+               unlock_page(page);
+               return err;
+       }
        if (pde)
                pde->rec_len = ext2_rec_len_to_disk(to - from);
        dir->inode = 0;
@@ -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);
        EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL;
        mark_inode_dirty(inode);
-       err = ext2_handle_dirsync(inode);
-out:
-       return err;
+       return ext2_handle_dirsync(inode);
 }
 
 /*
index 7f5dfa8..dafdd2d 100644 (file)
@@ -335,18 +335,16 @@ static int ext2_rename (struct mnt_idmap * idmap,
 
        err = dquot_initialize(old_dir);
        if (err)
-               goto out;
+               return err;
 
        err = dquot_initialize(new_dir);
        if (err)
-               goto out;
+               return err;
 
        old_de = ext2_find_entry(old_dir, &old_dentry->d_name, &old_page,
                                 &old_page_addr);
-       if (IS_ERR(old_de)) {
-               err = PTR_ERR(old_de);
-               goto out;
-       }
+       if (IS_ERR(old_de))
+               return PTR_ERR(old_de);
 
        if (S_ISDIR(old_inode->i_mode)) {
                err = -EIO;
@@ -394,27 +392,20 @@ static int ext2_rename (struct mnt_idmap * idmap,
        old_inode->i_ctime = current_time(old_inode);
        mark_inode_dirty(old_inode);
 
-       ext2_delete_entry(old_de, old_page, old_page_addr);
-
-       if (dir_de) {
-               if (old_dir != new_dir) {
+       err = ext2_delete_entry(old_de, old_page, old_page_addr);
+       if (!err && dir_de) {
+               if (old_dir != new_dir)
                        err = ext2_set_link(old_inode, dir_de, dir_page,
                                            dir_page_addr, new_dir, false);
 
-               }
-               ext2_put_page(dir_page, dir_page_addr);
                inode_dec_link_count(old_dir);
        }
-
-out_old:
-       ext2_put_page(old_page, old_page_addr);
-out:
-       return err;
-
 out_dir:
        if (dir_de)
                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 = {