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

libaokun (A) libaokun1 at huawei.com
Wed Mar 16 19:31:57 PDT 2022


在 2022/3/17 6:00, Richard Weinberger 写道:
> ----- Ursprüngliche Mail -----
>> Von: "libaokun" <libaokun1 at huawei.com>
>> An: "richard" <richard at nod.at>, "linux-mtd" <linux-mtd at lists.infradead.org>, "linux-kernel"
>> <linux-kernel at vger.kernel.org>
>> CC: "yukuai3" <yukuai3 at huawei.com>, "chengzhihao1" <chengzhihao1 at huawei.com>, "libaokun" <libaokun1 at huawei.com>
>> 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 at huawei.com>
>>> Signed-off-by: Baokun Li <libaokun1 at huawei.com>
>>> ---
>>>    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




More information about the linux-mtd mailing list