From 0013b8ce24b7face67934b207303db71fa1c0e55 Mon Sep 17 00:00:00 2001 From: Dmitry Monakhov Date: Wed, 12 Jun 2013 22:25:07 -0400 Subject: [PATCH] --- yaml --- r: 377615 b: refs/heads/master c: 06a407f13daf9e48f0ef7189c7e54082b53940c7 h: refs/heads/master i: 377613: e51c9dd83f542036d909d5362fd18eda2f6aab83 377611: 57e791a1c7b628f571c60f2589d393f26934d57b 377607: 54b844a6c4ee5692fb1d7115a435f69fb3030599 377599: 6bf9df42cc4d2ac52d78a067ba15a817e3c94d8b v: v3 --- [refs] | 2 +- trunk/fs/ext4/super.c | 36 +++++++++++++++++++++++++++++++++++- trunk/include/linux/jbd2.h | 13 +++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 98b92e704feb..4a78bdecd7bd 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9ff864462477206bc23b405a6ae506e92fb6dc9c +refs/heads/master: 06a407f13daf9e48f0ef7189c7e54082b53940c7 diff --git a/trunk/fs/ext4/super.c b/trunk/fs/ext4/super.c index 7c8e1713e203..0f77c2e4b888 100644 --- a/trunk/fs/ext4/super.c +++ b/trunk/fs/ext4/super.c @@ -69,6 +69,7 @@ static void ext4_mark_recovery_complete(struct super_block *sb, static void ext4_clear_journal_err(struct super_block *sb, struct ext4_super_block *es); static int ext4_sync_fs(struct super_block *sb, int wait); +static int ext4_sync_fs_nojournal(struct super_block *sb, int wait); static int ext4_remount(struct super_block *sb, int *flags, char *data); static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf); static int ext4_unfreeze(struct super_block *sb); @@ -1097,6 +1098,7 @@ static const struct super_operations ext4_nojournal_sops = { .dirty_inode = ext4_dirty_inode, .drop_inode = ext4_drop_inode, .evict_inode = ext4_evict_inode, + .sync_fs = ext4_sync_fs_nojournal, .put_super = ext4_put_super, .statfs = ext4_statfs, .remount_fs = ext4_remount, @@ -4553,6 +4555,7 @@ static int ext4_sync_fs(struct super_block *sb, int wait) { int ret = 0; tid_t target; + bool needs_barrier = false; struct ext4_sb_info *sbi = EXT4_SB(sb); trace_ext4_sync_fs(sb, wait); @@ -4563,10 +4566,41 @@ static int ext4_sync_fs(struct super_block *sb, int wait) * no dirty dquots */ dquot_writeback_dquots(sb, -1); + /* + * Data writeback is possible w/o journal transaction, so barrier must + * being sent at the end of the function. But we can skip it if + * transaction_commit will do it for us. + */ + target = jbd2_get_latest_transaction(sbi->s_journal); + if (wait && sbi->s_journal->j_flags & JBD2_BARRIER && + !jbd2_trans_will_send_data_barrier(sbi->s_journal, target)) + needs_barrier = true; + if (jbd2_journal_start_commit(sbi->s_journal, &target)) { if (wait) - jbd2_log_wait_commit(sbi->s_journal, target); + ret = jbd2_log_wait_commit(sbi->s_journal, target); + } + if (needs_barrier) { + int err; + err = blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL); + if (!ret) + ret = err; } + + return ret; +} + +static int ext4_sync_fs_nojournal(struct super_block *sb, int wait) +{ + int ret = 0; + + trace_ext4_sync_fs(sb, wait); + flush_workqueue(EXT4_SB(sb)->rsv_conversion_wq); + flush_workqueue(EXT4_SB(sb)->unrsv_conversion_wq); + dquot_writeback_dquots(sb, -1); + if (wait && test_opt(sb, BARRIER)) + ret = blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL); + return ret; } diff --git a/trunk/include/linux/jbd2.h b/trunk/include/linux/jbd2.h index c3645b9475f1..a79783faecad 100644 --- a/trunk/include/linux/jbd2.h +++ b/trunk/include/linux/jbd2.h @@ -1374,6 +1374,19 @@ static inline u32 jbd2_chksum(journal_t *journal, u32 crc, return *(u32 *)desc.ctx; } +/* Return most recent uncommitted transaction */ +static inline tid_t jbd2_get_latest_transaction(journal_t *journal) +{ + tid_t tid; + + read_lock(&journal->j_state_lock); + tid = journal->j_commit_request; + if (journal->j_running_transaction) + tid = journal->j_running_transaction->t_tid; + read_unlock(&journal->j_state_lock); + return tid; +} + #ifdef __KERNEL__ #define buffer_trace_init(bh) do {} while (0)