ext2: propagate errors from ext2_prepare_chunk
authorChristoph Hellwig <hch@lst.de>
Mon, 16 Jan 2023 08:52:05 +0000 (09:52 +0100)
committerJan Kara <jack@suse.cz>
Mon, 16 Jan 2023 11:19:25 +0000 (12:19 +0100)
Propagate errors from ext2_prepare_chunk to the callers and handle them
there.  While touching the prototype also turn update_times into a bool
from the current int used as bool.

[JK: fixed up error recovery path in ext2_rename()]

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jan Kara <jack@suse.cz>
Message-Id: <20230116085205.2342975-1-hch@lst.de>

fs/ext2/dir.c
fs/ext2/ext2.h
fs/ext2/namei.c

index 0f144c5c78613adef64b680984287efa320d9b99..4a6955a0a116de88a597b3ca0abaf6201d594a66 100644 (file)
@@ -461,9 +461,9 @@ static int ext2_handle_dirsync(struct inode *dir)
        return err;
 }
 
-void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
-                  struct page *page, void *page_addr, struct inode *inode,
-                  int update_times)
+int ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
+               struct page *page, void *page_addr, struct inode *inode,
+               bool update_times)
 {
        loff_t pos = page_offset(page) +
                        (char *) de - (char *) page_addr;
@@ -472,7 +472,10 @@ void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
 
        lock_page(page);
        err = ext2_prepare_chunk(page, pos, len);
-       BUG_ON(err);
+       if (err) {
+               unlock_page(page);
+               return err;
+       }
        de->inode = cpu_to_le32(inode->i_ino);
        ext2_set_de_type(de, inode);
        ext2_commit_chunk(page, pos, len);
@@ -480,7 +483,7 @@ void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
                dir->i_mtime = dir->i_ctime = current_time(dir);
        EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
        mark_inode_dirty(dir);
-       ext2_handle_dirsync(dir);
+       return ext2_handle_dirsync(dir);
 }
 
 /*
index 28de11a22e5f6cbc957a599e09508b8a75902175..f7f590aac55a001da5b1aa1e3d8f208230d0a8a0 100644 (file)
@@ -734,8 +734,9 @@ extern int ext2_delete_entry(struct ext2_dir_entry_2 *dir, struct page *page,
                             char *kaddr);
 extern int ext2_empty_dir (struct inode *);
 extern struct ext2_dir_entry_2 *ext2_dotdot(struct inode *dir, struct page **p, void **pa);
-extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, void *,
-                         struct inode *, int);
+int ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
+               struct page *page, void *page_addr, struct inode *inode,
+               bool update_times);
 static inline void ext2_put_page(struct page *page, void *page_addr)
 {
        kunmap_local(page_addr);
index c056957221a22563cd90f8c1e30dc8bec44d736f..9805bc3ee80b215908f54da7a892ddb9174bb17e 100644 (file)
@@ -370,8 +370,11 @@ static int ext2_rename (struct user_namespace * mnt_userns,
                        err = PTR_ERR(new_de);
                        goto out_dir;
                }
-               ext2_set_link(new_dir, new_de, new_page, page_addr, old_inode, 1);
+               err = ext2_set_link(new_dir, new_de, new_page, page_addr,
+                                   old_inode, true);
                ext2_put_page(new_page, page_addr);
+               if (err)
+                       goto out_dir;
                new_inode->i_ctime = current_time(new_inode);
                if (dir_de)
                        drop_nlink(new_inode);
@@ -394,24 +397,24 @@ static int ext2_rename (struct user_namespace * mnt_userns,
        ext2_delete_entry(old_de, old_page, old_page_addr);
 
        if (dir_de) {
-               if (old_dir != new_dir)
-                       ext2_set_link(old_inode, dir_de, dir_page,
-                                     dir_page_addr, new_dir, 0);
+               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);
-       return 0;
+out:
+       return err;
 
 out_dir:
        if (dir_de)
                ext2_put_page(dir_page, dir_page_addr);
-out_old:
-       ext2_put_page(old_page, old_page_addr);
-out:
-       return err;
+       goto out_old;
 }
 
 const struct inode_operations ext2_dir_inode_operations = {