Re: sync filesystem of overlayfs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Amir

Per the previous discussion, my opinion is calling __sync_filesystem() in ovl_sync_fs()
would be better for current stage. If we pick up overlayfs’s dirty inodes we may need to
involve writeback and cgroup logics in overlayfs and put all things into sync_fs seems 
quite heavy and complex. If you agree I’ll make new patch for review.



Best Regards,
Chengguang



> 在 2017年11月27日,下午7:30,Amir Goldstein <amir73il@xxxxxxxxx> 写道:
> 
> On Mon, Nov 27, 2017 at 12:31 PM, cgxu <cgxu@xxxxxxxxxxxx> wrote:
>> 
>> 
>>> 在 2017年11月27日,下午4:59,Amir Goldstein <amir73il@xxxxxxxxx> 写道:
>>> 
>>> On Mon, Nov 27, 2017 at 10:08 AM, cgxu <cgxu@xxxxxxxxxxxx> wrote:
>>>> 
>>>> Hi,
>>>> 
>>>> Recently I found syncfs and umount could not make data consistency in overlayfs.
>>>> I did some investigations and now I know synchronization didn’t directly happen
>>>> in upperdir filesystem during these operations executed in overlayfs.
>>>> 
>>> 
>>> Can you share the method of your investigation?
>>> Maybe make it into an xfstest?
>>> You can probably use dmflakey target.
>> 
>> Testing method as below. (I tested in virtual machine)
>> 
>> 1. stop bd_writeback behavior by adjusting parameters in /proc/sys/vm/
>> 2. copy a large file to overlayfs directory and then do syncfs or umount.
>> 3. power off && power on
>> 4. compare content of files using diff.
>> 
>> and I also applied below simple quick patch (may need more check for detail) to check fixing result.
>> 
>> -----------
>> $ git diff
>> diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
>> index 7b64d5c..3ab25a7 100644
>> --- a/fs/overlayfs/super.c
>> +++ b/fs/overlayfs/super.c
>> @@ -1222,11 +1222,24 @@ static struct dentry *ovl_mount(struct file_system_type *fs_type, int flags,
>>        return mount_nodev(fs_type, flags, raw_data, ovl_fill_super);
>> }
>> 
>> +static void ovl_kill_super(struct super_block *sb)
>> +{
>> +        struct ovl_fs *ufs = sb->s_fs_info;
>> +       struct super_block *real_super = ufs->upper_mnt->mnt_sb;
>> +
>> +        if (!(sb->s_flags & MS_RDONLY)) {
>> +                down_read(&real_super->s_umount);
>> +                sync_filesystem(real_super);
>> +                up_read(&real_super->s_umount);
>> +        }
>> +        kill_anon_super(sb);
>> +}
>> +
> 
> kill_anon_super() -> generic_shutdown_super() -> sync_filesystem()
> 
> So your implementation should go into ovl_sync_fs instead to cover
> other cases like freeze_super() and plain syncfs().
> 
>> static struct file_system_type ovl_fs_type = {
>>        .owner          = THIS_MODULE,
>>        .name           = "overlay",
>>        .mount          = ovl_mount,
>> -       .kill_sb        = kill_anon_super,
>> +       .kill_sb        = ovl_kill_super,
>> };
>> MODULE_ALIAS_FS("overlay");
>> 
>> diff --git a/fs/sync.c b/fs/sync.c
>> index 83ac79a..d49792c 100644
>> --- a/fs/sync.c
>> +++ b/fs/sync.c
>> @@ -161,6 +161,8 @@ void emergency_sync(void)
>>        if (!f.file)
>>                return -EBADF;
>>        sb = f.file->f_path.dentry->d_sb;
>> +       if (!(sb->s_flags & MS_RDONLY))
>> +               sb = d_real(f.file->f_path.dentry, NULL, f.file->f_flags, 0)->d_sb;
>> 
> 
> No reason to change vfs.
> sync_filesystem() calls ovl_sync_fs() where upper fs can be synced.
> 
>>        down_read(&sb->s_umount);
>>        ret = sync_filesystem(sb);
>> 
>> 
>> -----------
>> 
>> 
>>> 
>>>> I'm also confused by below comment in function ovl_sync_fs() in super.c
>>>> 
>>>> /* real inodes have already been synced by sync_filesystem(ovl_sb) */
>>>> 
>>>> In my understanding sync_filesystem(ovl_sb) can not make real inodes synced
>>>> unless delivers real superblock of upperdir filesystem to sync_filesystem().
>>>> 
>>>> I can’t make sure current implementation is by design or for some other reasons because
>>>> sync upperdir filesystem may be a little bit heavy especially in a large filesystem.
>>>> Could anyone give me a hint for this?
>>>> 
>>> 
>>> Looks like you are right.
>>> That comment I wrote is an oversight, not by design, although the concern
>>> that you raise is valid.
>>> 
>>>> If this problem needs to be fix, I’ll try to make a patch for review.
>>>> 
>>> 
>>> So the simple way would be to call __sync_filesystem() from ovl_sync_fs()
>>> instead of calling upper_sb->s_op->sync_fs(), but that would be heavy
>>> as you said.
>>> A better fix would be to iterate overlay sb inodes and flush only the dirty
>>> ovl_inode_upper() pages, before calling upper_sb->s_op->sync_fs().
>>> 
>>> I didn't look closely to see how complex that would be, so let me know what
>>> you think is best.
>> 
>> The easiest way is as you said or like quick patch above,
>> but sync_fs() seems like doing superblock related things only in most case.
>> 
> 
> It does everything that generic vfs sync_filesystem() doesn't do.
> In overlayfs case, that is syncing upper fs.
> 
>> For me maybe ideal way is define new virtual BDI for overlayfs,
>> and using that to organize dirty inodes, so that we don’t have to put much
>> effort to looking for target inodes. If this approach makes sense I’ll
>> carefully consider detail.
>> 
>> We can just fix this problem in simple way first and consider
>> better solution later because that is probably related to many complex things.
>> 
> 
> Agree. Safety first!
> 
>> I think for most people umount or sync_fs takes time is acceptable and at least
>> it is much better than data inconsistency.
>> 
> 
> Not sure about that. I heard there are use cases for containers for
> which the time
> of mount/umount matters.
> We'll have to see about that.
> 
> Thanks,
> Amir.

--
To unsubscribe from this list: send the line "unsubscribe linux-unionfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Filesystems Devel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux