Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[platform/adaptation/renesas_rcar/renesas_kernel.git] / fs / hfsplus / super.c
index a9bca4b..fdafb2d 100644 (file)
@@ -124,7 +124,7 @@ static int hfsplus_system_write_inode(struct inode *inode)
 
        if (fork->total_size != cpu_to_be64(inode->i_size)) {
                set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags);
-               inode->i_sb->s_dirt = 1;
+               hfsplus_mark_mdb_dirty(inode->i_sb);
        }
        hfsplus_inode_write_fork(inode, fork);
        if (tree)
@@ -161,7 +161,7 @@ static void hfsplus_evict_inode(struct inode *inode)
        }
 }
 
-int hfsplus_sync_fs(struct super_block *sb, int wait)
+static int hfsplus_sync_fs(struct super_block *sb, int wait)
 {
        struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
        struct hfsplus_vh *vhdr = sbi->s_vhdr;
@@ -171,9 +171,7 @@ int hfsplus_sync_fs(struct super_block *sb, int wait)
        if (!wait)
                return 0;
 
-       dprint(DBG_SUPER, "hfsplus_write_super\n");
-
-       sb->s_dirt = 0;
+       dprint(DBG_SUPER, "hfsplus_sync_fs\n");
 
        /*
         * Explicitly write out the special metadata inodes.
@@ -226,12 +224,34 @@ out:
        return error;
 }
 
-static void hfsplus_write_super(struct super_block *sb)
+static void delayed_sync_fs(struct work_struct *work)
 {
-       if (!(sb->s_flags & MS_RDONLY))
-               hfsplus_sync_fs(sb, 1);
-       else
-               sb->s_dirt = 0;
+       struct hfsplus_sb_info *sbi;
+
+       sbi = container_of(work, struct hfsplus_sb_info, sync_work.work);
+
+       spin_lock(&sbi->work_lock);
+       sbi->work_queued = 0;
+       spin_unlock(&sbi->work_lock);
+
+       hfsplus_sync_fs(sbi->alloc_file->i_sb, 1);
+}
+
+void hfsplus_mark_mdb_dirty(struct super_block *sb)
+{
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+       unsigned long delay;
+
+       if (sb->s_flags & MS_RDONLY)
+               return;
+
+       spin_lock(&sbi->work_lock);
+       if (!sbi->work_queued) {
+               delay = msecs_to_jiffies(dirty_writeback_interval * 10);
+               queue_delayed_work(system_long_wq, &sbi->sync_work, delay);
+               sbi->work_queued = 1;
+       }
+       spin_unlock(&sbi->work_lock);
 }
 
 static void hfsplus_put_super(struct super_block *sb)
@@ -240,8 +260,7 @@ static void hfsplus_put_super(struct super_block *sb)
 
        dprint(DBG_SUPER, "hfsplus_put_super\n");
 
-       if (!sb->s_fs_info)
-               return;
+       cancel_delayed_work_sync(&sbi->sync_work);
 
        if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) {
                struct hfsplus_vh *vhdr = sbi->s_vhdr;
@@ -328,7 +347,6 @@ static const struct super_operations hfsplus_sops = {
        .write_inode    = hfsplus_write_inode,
        .evict_inode    = hfsplus_evict_inode,
        .put_super      = hfsplus_put_super,
-       .write_super    = hfsplus_write_super,
        .sync_fs        = hfsplus_sync_fs,
        .statfs         = hfsplus_statfs,
        .remount_fs     = hfsplus_remount,
@@ -347,7 +365,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
        u64 last_fs_block, last_fs_page;
        int err;
 
-       err = -EINVAL;
+       err = -ENOMEM;
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                goto out;
@@ -355,6 +373,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_fs_info = sbi;
        mutex_init(&sbi->alloc_mutex);
        mutex_init(&sbi->vh_mutex);
+       spin_lock_init(&sbi->work_lock);
+       INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs);
        hfsplus_fill_defaults(sbi);
 
        err = -EINVAL;