]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.19
authorSasha Levin <sashal@kernel.org>
Sun, 17 Jan 2021 16:12:52 +0000 (11:12 -0500)
committerSasha Levin <sashal@kernel.org>
Sun, 17 Jan 2021 16:12:52 +0000 (11:12 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.19/ext4-fix-bug-for-rename-with-rename_whiteout.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/ext4-fix-bug-for-rename-with-rename_whiteout.patch b/queue-4.19/ext4-fix-bug-for-rename-with-rename_whiteout.patch
new file mode 100644 (file)
index 0000000..7175fc3
--- /dev/null
@@ -0,0 +1,104 @@
+From dd84a8b95f91f69bf752d0973ab674f75450955f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Jan 2021 14:28:57 +0800
+Subject: ext4: fix bug for rename with RENAME_WHITEOUT
+
+From: yangerkun <yangerkun@huawei.com>
+
+[ Upstream commit 6b4b8e6b4ad8553660421d6360678b3811d5deb9 ]
+
+We got a "deleted inode referenced" warning cross our fsstress test. The
+bug can be reproduced easily with following steps:
+
+  cd /dev/shm
+  mkdir test/
+  fallocate -l 128M img
+  mkfs.ext4 -b 1024 img
+  mount img test/
+  dd if=/dev/zero of=test/foo bs=1M count=128
+  mkdir test/dir/ && cd test/dir/
+  for ((i=0;i<1000;i++)); do touch file$i; done # consume all block
+  cd ~ && renameat2(AT_FDCWD, /dev/shm/test/dir/file1, AT_FDCWD,
+    /dev/shm/test/dir/dst_file, RENAME_WHITEOUT) # ext4_add_entry in
+    ext4_rename will return ENOSPC!!
+  cd /dev/shm/ && umount test/ && mount img test/ && ls -li test/dir/file1
+  We will get the output:
+  "ls: cannot access 'test/dir/file1': Structure needs cleaning"
+  and the dmesg show:
+  "EXT4-fs error (device loop0): ext4_lookup:1626: inode #2049: comm ls:
+  deleted inode referenced: 139"
+
+ext4_rename will create a special inode for whiteout and use this 'ino'
+to replace the source file's dir entry 'ino'. Once error happens
+latter(the error above was the ENOSPC return from ext4_add_entry in
+ext4_rename since all space has been consumed), the cleanup do drop the
+nlink for whiteout, but forget to restore 'ino' with source file. This
+will trigger the bug describle as above.
+
+Signed-off-by: yangerkun <yangerkun@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Cc: stable@vger.kernel.org
+Fixes: cd808deced43 ("ext4: support RENAME_WHITEOUT")
+Link: https://lore.kernel.org/r/20210105062857.3566-1-yangerkun@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/namei.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 3c238006870d3..8f7e0ad5b5ef1 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3437,8 +3437,6 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent,
+                       return retval;
+               }
+       }
+-      brelse(ent->bh);
+-      ent->bh = NULL;
+       return 0;
+ }
+@@ -3638,6 +3636,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+               }
+       }
++      old_file_type = old.de->file_type;
+       if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir))
+               ext4_handle_sync(handle);
+@@ -3665,7 +3664,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+       force_reread = (new.dir->i_ino == old.dir->i_ino &&
+                       ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA));
+-      old_file_type = old.de->file_type;
+       if (whiteout) {
+               /*
+                * Do this before adding a new entry, so the old entry is sure
+@@ -3737,15 +3735,19 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
+       retval = 0;
+ end_rename:
+-      brelse(old.dir_bh);
+-      brelse(old.bh);
+-      brelse(new.bh);
+       if (whiteout) {
+-              if (retval)
++              if (retval) {
++                      ext4_setent(handle, &old,
++                              old.inode->i_ino, old_file_type);
+                       drop_nlink(whiteout);
++              }
+               unlock_new_inode(whiteout);
+               iput(whiteout);
++
+       }
++      brelse(old.dir_bh);
++      brelse(old.bh);
++      brelse(new.bh);
+       if (handle)
+               ext4_journal_stop(handle);
+       return retval;
+-- 
+2.27.0
+
index a6ac6ca39f42054b02b2b96e285fcc24ea06c077..73ec1f6a5acf33d5e828c65bda9c231384c50c18 100644 (file)
@@ -9,3 +9,4 @@ mm-hugetlb-fix-potential-missing-huge-page-size-info.patch
 dm-snapshot-flush-merged-data-before-committing-metadata.patch
 dm-integrity-fix-the-maximum-number-of-arguments.patch
 r8152-add-lenovo-powered-usb-c-travel-hub.patch
+ext4-fix-bug-for-rename-with-rename_whiteout.patch