--- a/fs/ext4/inode.c 2009-04-13 23:54:38.000000000 +0000 +++ b/fs/ext4/inode.c 2009-04-13 23:54:30.000000000 +0000 @@ -46,10 +46,8 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode, loff_t new_size) { - return jbd2_journal_begin_ordered_truncate( - EXT4_SB(inode->i_sb)->s_journal, - &EXT4_I(inode)->jinode, - new_size); + return jbd2_journal_begin_ordered_truncate(&EXT4_I(inode)->jinode, + new_size); } static void ext4_invalidatepage(struct page *page, unsigned long offset); --- a/fs/jbd2/transaction.c 2009-04-13 23:56:00.000000000 +0000 +++ b/fs/jbd2/transaction.c 2009-04-13 23:55:49.000000000 +0000 @@ -2050,46 +2050,26 @@ done: } /* - * File truncate and transaction commit interact with each other in a - * non-trivial way. If a transaction writing data block A is - * committing, we cannot discard the data by truncate until we have - * written them. Otherwise if we crashed after the transaction with - * write has committed but before the transaction with truncate has - * committed, we could see stale data in block A. This function is a - * helper to solve this problem. It starts writeout of the truncated - * part in case it is in the committing transaction. - * - * Filesystem code must call this function when inode is journaled in - * ordered mode before truncation happens and after the inode has been - * placed on orphan list with the new inode size. The second condition - * avoids the race that someone writes new data and we start - * committing the transaction after this function has been called but - * before a transaction for truncate is started (and furthermore it - * allows us to optimize the case where the addition to orphan list - * happens in the same transaction as write --- we don't have to write - * any data in such case). + * This function must be called when inode is journaled in ordered mode + * before truncation happens. It starts writeout of truncated part in + * case it is in the committing transaction so that we stand to ordered + * mode consistency guarantees. */ -int jbd2_journal_begin_ordered_truncate(journal_t *journal, - struct jbd2_inode *jinode, +int jbd2_journal_begin_ordered_truncate(struct jbd2_inode *inode, loff_t new_size) { - transaction_t *inode_trans, *commit_trans; + journal_t *journal; + transaction_t *commit_trans; int ret = 0; - /* This is a quick check to avoid locking if not necessary */ - if (!jinode->i_transaction) + if (!inode->i_transaction && !inode->i_next_transaction) goto out; - /* Locks are here just to force reading of recent values, it is - * enough that the transaction was not committing before we started - * a transaction adding the inode to orphan list */ + journal = inode->i_transaction->t_journal; spin_lock(&journal->j_state_lock); commit_trans = journal->j_committing_transaction; spin_unlock(&journal->j_state_lock); - spin_lock(&journal->j_list_lock); - inode_trans = jinode->i_transaction; - spin_unlock(&journal->j_list_lock); - if (inode_trans == commit_trans) { - ret = filemap_fdatawrite_range(jinode->i_vfs_inode->i_mapping, + if (inode->i_transaction == commit_trans) { + ret = filemap_fdatawrite_range(inode->i_vfs_inode->i_mapping, new_size, LLONG_MAX); if (ret) jbd2_journal_abort(journal, ret); --- a/fs/ocfs2/journal.h 2009-04-13 23:56:53.000000000 +0000 +++ b/fs/ocfs2/journal.h 2009-04-13 23:56:44.000000000 +0000 @@ -445,10 +445,8 @@ static inline int ocfs2_jbd2_file_inode( static inline int ocfs2_begin_ordered_truncate(struct inode *inode, loff_t new_size) { - return jbd2_journal_begin_ordered_truncate( - OCFS2_SB(inode->i_sb)->journal->j_journal, - &OCFS2_I(inode)->ip_jinode, - new_size); + return jbd2_journal_begin_ordered_truncate(&OCFS2_I(inode)->ip_jinode, + new_size); } #endif /* OCFS2_JOURNAL_H */ --- a/include/linux/jbd2.h 2009-04-13 23:57:40.000000000 +0000 +++ b/include/linux/jbd2.h 2009-04-13 23:57:33.000000000 +0000 @@ -1087,8 +1087,7 @@ extern int jbd2_journal_clear_err (j extern int jbd2_journal_bmap(journal_t *, unsigned long, unsigned long long *); extern int jbd2_journal_force_commit(journal_t *); extern int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *inode); -extern int jbd2_journal_begin_ordered_truncate(journal_t *journal, - struct jbd2_inode *inode, loff_t new_size); +extern int jbd2_journal_begin_ordered_truncate(struct jbd2_inode *inode, loff_t new_size); extern void jbd2_journal_init_jbd_inode(struct jbd2_inode *jinode, struct inode *inode); extern void jbd2_journal_release_jbd_inode(journal_t *journal, struct jbd2_inode *jinode);