Re: [PATCH] ovl: Sync upper dirty data when sync overlayfs

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

 



> 在 2017年11月28日,下午2:47,Amir Goldstein <amir73il@xxxxxxxxx> 写道:
> 
> On Tue, Nov 28, 2017 at 6:40 AM, Chengguang Xu <cgxu@xxxxxxxxxxxx> wrote:
>> Executes filesystem sync or umount on overlayfs, dirty data does not be synced as expected on upper filesystem.
>> This patch fixes sync filesystem method to keep data consistency for overlayfs.
>> 
>> Signed-off-by: Chengguang Xu <cgxu@xxxxxxxxxxxx>
>> ---
>> fs/overlayfs/super.c | 24 ++++++++++++++++++++----
>> 1 file changed, 20 insertions(+), 4 deletions(-)
>> 
>> diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
>> index f5738e9..9c54345 100644
>> --- a/fs/overlayfs/super.c
>> +++ b/fs/overlayfs/super.c
>> @@ -17,6 +17,7 @@
>> #include <linux/statfs.h>
>> #include <linux/seq_file.h>
>> #include <linux/posix_acl_xattr.h>
>> +#include <linux/writeback.h>
>> #include "overlayfs.h"
>> #include "ovl_entry.h"
>> 
>> @@ -231,6 +232,7 @@ static void ovl_put_super(struct super_block *sb)
>>        kfree(ufs);
>> }
>> 
>> +/* Sync real dirty inodes in upper filesystem (if it exists) */
>> static int ovl_sync_fs(struct super_block *sb, int wait)
>> {
>>        struct ovl_fs *ufs = sb->s_fs_info;
>> @@ -240,12 +242,26 @@ static int ovl_sync_fs(struct super_block *sb, int wait)
>>        if (!ufs->upper_mnt)
>>                return 0;
>>        upper_sb = ufs->upper_mnt->mnt_sb;
>> -       if (!upper_sb->s_op->sync_fs)
>> -               return 0;
>> 
>> -       /* real inodes have already been synced by sync_filesystem(ovl_sb) */
>>        down_read(&upper_sb->s_umount);
>> -       ret = upper_sb->s_op->sync_fs(upper_sb, wait);
>> +       if (wait)
>> +               sync_inodes_sb(upper_sb);
>> +       else
>> +               writeback_inodes_sb(upper_sb, WB_REASON_SYNC);
>> +
>> +       if (upper_sb->s_op->sync_fs)
>> +               upper_sb->s_op->sync_fs(upper_sb, wait);
>> +
>> +       if (!upper_sb->s_bdev) {
>> +               up_read(&upper_sb->s_umount);
>> +               return 0;
>> +       }
>> +
>> +       if (wait)
>> +               ret = filemap_write_and_wait(upper_sb->s_bdev->bd_inode->i_mapping);
>> +       else
>> +               ret = filemap_flush(upper_sb->s_bdev->bd_inode->i_mapping);
>> +
>>        up_read(&upper_sb->s_umount);
>>        return ret;
>> }
> 
> 
> Unless I am missing something subtle here, you should export vfs
> __sync_filesystem and call it from here instead of duplicating it.
> Any technical reason not to do it?
> 

Actually, not a technical reason. How about below modification?
If it looks good I’ll send patch on new mail thread.


diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index f5738e9..736f04d 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -231,6 +231,7 @@ static void ovl_put_super(struct super_block *sb)
        kfree(ufs);
 }

+/* Sync real dirty inodes in upper filesystem (if it exists) */
 static int ovl_sync_fs(struct super_block *sb, int wait)
 {
        struct ovl_fs *ufs = sb->s_fs_info;
@@ -240,12 +241,9 @@ static int ovl_sync_fs(struct super_block *sb, int wait)
        if (!ufs->upper_mnt)
                return 0;
        upper_sb = ufs->upper_mnt->mnt_sb;
-       if (!upper_sb->s_op->sync_fs)
-               return 0;

-       /* real inodes have already been synced by sync_filesystem(ovl_sb) */
        down_read(&upper_sb->s_umount);
-       ret = upper_sb->s_op->sync_fs(upper_sb, wait);
+       ret = __sync_filesystem(upper_sb, wait);
        up_read(&upper_sb->s_umount);
        return ret;
 }
diff --git a/fs/sync.c b/fs/sync.c
index 83ac79a..76c913e 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -28,7 +28,7 @@
  * wait == 1 case since in that case write_inode() functions do
  * sync_dirty_buffer() and thus effectively write one block at a time.
  */
-static int __sync_filesystem(struct super_block *sb, int wait)
+int __sync_filesystem(struct super_block *sb, int wait)
 {
        if (wait)
                sync_inodes_sb(sb);
@@ -39,6 +39,7 @@ static int __sync_filesystem(struct super_block *sb, int wait)
                sb->s_op->sync_fs(sb, wait);
        return __sync_blockdev(sb->s_bdev, wait);
 }
+EXPORT_SYMBOL(__sync_filesystem);

 /*
  * Write out and wait upon all dirty data associated with this
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 885266a..ef03b18 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2464,6 +2464,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb)
 }
 #endif
 extern int sync_filesystem(struct super_block *);
+extern int __sync_filesystem(struct super_block *, int);
 extern const struct file_operations def_blk_fops;
 extern const struct file_operations def_chr_fops;
 #ifdef CONFIG_BLOCK


> 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
> 

--
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