Re: [PATCH -next] ubifs: rename_whiteout: correct old_dir size computing

From: libaokun (A)
Date: Wed Mar 16 2022 - 22:32:05 EST


在 2022/3/17 6:00, Richard Weinberger 写道:
----- Ursprüngliche Mail -----
Von: "libaokun" <libaokun1@xxxxxxxxxx>
An: "richard" <richard@xxxxxx>, "linux-mtd" <linux-mtd@xxxxxxxxxxxxxxxxxxx>, "linux-kernel"
<linux-kernel@xxxxxxxxxxxxxxx>
CC: "yukuai3" <yukuai3@xxxxxxxxxx>, "chengzhihao1" <chengzhihao1@xxxxxxxxxx>, "libaokun" <libaokun1@xxxxxxxxxx>
Gesendet: Donnerstag, 10. März 2022 09:32:57
Betreff: Re: [PATCH -next] ubifs: rename_whiteout: correct old_dir size computing
A gentle ping, sorry for the noise.
I have to say sorry for the day.
Thanks for your patience with me.
Please don't feel bad about it.
Glad to hear from you! Thanks for your kindly reply!
在 2022/2/15 12:07, Baokun Li 写道:
When renaming the whiteout file, the old whiteout file is not deleted.
Therefore, we add the old dentry size to the old dir like XFS.
Otherwise, an error may be reported due to `fscki->calc_sz != fscki->size`
in check_indes.

Fixes: 9e0a1fff8db56ea ("ubifs: Implement RENAME_WHITEOUT")
Reported-by: Zhihao Cheng <chengzhihao1@xxxxxxxxxx>
Signed-off-by: Baokun Li <libaokun1@xxxxxxxxxx>
---
fs/ubifs/dir.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index ae082a0be2a3..86151889548e 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1402,6 +1402,9 @@ static int do_rename(struct inode *old_dir, struct dentry
*old_dentry,
iput(whiteout);
goto out_release;
}
+
+ /* Add the old_dentry size to the old_dir size. */
+ old_sz -= CALC_DENT_SIZE(fname_len(&old_nm));
So you basically reset old_sz back to 0?
Yes, reset old_sz to 0 here.
Since the old file remains in old_dir after whiteout_rename,
nothing has changed, we just add new_sz to the new folder.

Here, old_sz is the value to be subtracted from old_dir->i_size,
which is initialized to `CALC_DENT_SIZE(fname_len(&old_nm));` .
In RENAME_WHITEOUT, because the old file is not deleted,
we need to subtract old_dent_size from old_sz after RENAME_WHITEOUT is complete, that is, set old_sz to 0.

we can easily reproduce this problem with the following script:
 ```C
// test_ubifs_whiteout.c
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/syscall.h>
 #include <linux/fs.h>

 int main(int argc, char *argv[])
 {
     system("touch /root/temp/file");
     syscall(SYS_renameat2, AT_FDCWD, "/root/temp/file", AT_FDCWD, "/root/temp/target", RENAME_WHITEOUT);
     return 0;
 }
 ```

```shell
#!/bin/bash
set -e
# ubifs_whiteout_reproducer.sh

TMP=/root/temp
umount $TMP 2>/dev/null || true
mkdir -p $TMP

modprobe -r ubifs 2>/dev/null || true
for i in $(seq 0 1)
do
    ubidetach -p /dev/mtd$i 2>/dev/null || true
done
modprobe -r ubi 2>/dev/null || true
modprobe -r nandsim 2>/dev/null || true
modprobe nandsim id_bytes="0xec,0xa1,0x00,0x15"
modprobe ubi mtd="0,512"
ubimkvol -N vol_a -m -n 0 /dev/ubi0
modprobe ubifs
mount -t ubifs /dev/ubi0_0 $TMP

./test_ubifs_whiteout
umount /dev/ubi0_0
echo 1 > /sys/kernel/debug/ubifs/chk_fs
mount -t ubifs /dev/ubi0_0 $TMP
```
Thanks,
//richard
.

--
With Best Regards,
Baokun Li