]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.9
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.9/ext4-fix-bug-for-rename-with-rename_whiteout.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/ext4-fix-bug-for-rename-with-rename_whiteout.patch b/queue-4.9/ext4-fix-bug-for-rename-with-rename_whiteout.patch
new file mode 100644 (file)
index 0000000..e2f97bc
--- /dev/null
@@ -0,0 +1,104 @@
+From aad43e019f4bcfbb80de8b0a695451ac1956a3f0 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 8ded38ac4cdef..6224b0e6fb643 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3421,8 +3421,6 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent,
+                       return retval;
+               }
+       }
+-      brelse(ent->bh);
+-      ent->bh = NULL;
+       return 0;
+ }
+@@ -3635,6 +3633,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);
+@@ -3662,7 +3661,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
+@@ -3734,15 +3732,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 7d5b66adeeeba11849acd01b2a11b554fcda320c..aa7c69a9ba0a2b205eaa91d35f1f4c7672ef88c7 100644 (file)
@@ -4,3 +4,4 @@ mips-fix-malformed-nt_file-and-nt_siginfo-in-32bit-coredumps.patch
 mips-relocatable-fix-possible-boot-hangup-with-kaslr-enabled.patch
 acpi-scan-harden-acpi_device_add-against-device-id-overflows.patch
 mm-hugetlb-fix-potential-missing-huge-page-size-info.patch
+ext4-fix-bug-for-rename-with-rename_whiteout.patch