2006-10-11 12:20:50 +04:00
/*
2006-10-11 12:20:53 +04:00
* linux / fs / ext4 / fsync . c
2006-10-11 12:20:50 +04:00
*
* Copyright ( C ) 1993 Stephen Tweedie ( sct @ redhat . com )
* from
* Copyright ( C ) 1992 Remy Card ( card @ masi . ibp . fr )
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie ( Paris VI )
* from
* linux / fs / minix / truncate . c Copyright ( C ) 1991 , 1992 Linus Torvalds
*
2006-10-11 12:20:53 +04:00
* ext4fs fsync primitive
2006-10-11 12:20:50 +04:00
*
* Big - endian to little - endian byte - swapping / bitmaps by
* David S . Miller ( davem @ caip . rutgers . edu ) , 1995
*
* Removed unnecessary code duplication for little endian machines
* and excessive __inline__s .
* Andi Kleen , 1997
*
* Major simplications and cleanup - we only need to do the metadata , because
* we can depend on generic_block_fdatasync ( ) to sync the data blocks .
*/
# include <linux/time.h>
# include <linux/fs.h>
# include <linux/sched.h>
# include <linux/writeback.h>
2006-10-11 12:21:01 +04:00
# include <linux/jbd2.h>
2008-07-12 03:27:31 +04:00
# include <linux/blkdev.h>
2009-06-17 19:48:11 +04:00
2008-04-30 02:13:32 +04:00
# include "ext4.h"
# include "ext4_jbd2.h"
2006-10-11 12:20:50 +04:00
2009-06-17 19:48:11 +04:00
# include <trace/events/ext4.h>
2006-10-11 12:20:50 +04:00
/*
2006-10-11 12:20:53 +04:00
* akpm : A new design for ext4_sync_file ( ) .
2006-10-11 12:20:50 +04:00
*
* This is only called from sys_fsync ( ) , sys_fdatasync ( ) and sys_msync ( ) .
* There cannot be a transaction open by this task .
* Another task could have dirtied this inode . Its data can be in any
* state in the journalling system .
*
* What we do is just kick off a commit and wait on it . This will snapshot the
* inode to disk .
2009-09-28 23:48:29 +04:00
*
* i_mutex lock is held when entering and exiting this function
2006-10-11 12:20:50 +04:00
*/
2008-09-09 06:25:24 +04:00
int ext4_sync_file ( struct file * file , struct dentry * dentry , int datasync )
2006-10-11 12:20:50 +04:00
{
struct inode * inode = dentry - > d_inode ;
2009-12-09 07:51:10 +03:00
struct ext4_inode_info * ei = EXT4_I ( inode ) ;
2008-07-12 03:27:31 +04:00
journal_t * journal = EXT4_SB ( inode - > i_sb ) - > s_journal ;
2009-12-09 07:51:10 +03:00
int ret ;
tid_t commit_tid ;
2006-10-11 12:20:50 +04:00
2007-10-17 02:38:25 +04:00
J_ASSERT ( ext4_journal_current_handle ( ) = = NULL ) ;
2006-10-11 12:20:50 +04:00
2009-06-17 19:48:11 +04:00
trace_ext4_sync_file ( file , dentry , datasync ) ;
2008-10-06 04:50:06 +04:00
2009-12-09 07:51:10 +03:00
if ( inode - > i_sb - > s_flags & MS_RDONLY )
return 0 ;
2010-03-02 21:28:44 +03:00
ret = flush_completed_IO ( inode ) ;
2009-09-28 23:48:29 +04:00
if ( ret < 0 )
2009-11-23 15:24:57 +03:00
return ret ;
2009-12-09 07:51:10 +03:00
if ( ! journal )
return simple_fsync ( file , dentry , datasync ) ;
2006-10-11 12:20:50 +04:00
/*
2009-12-09 07:51:10 +03:00
* data = writeback , ordered :
2006-10-11 12:20:50 +04:00
* The caller ' s filemap_fdatawrite ( ) / wait will sync the data .
2009-12-09 07:51:10 +03:00
* Metadata is in the journal , we wait for proper transaction to
* commit here .
2006-10-11 12:20:50 +04:00
*
* data = journal :
* filemap_fdatawrite won ' t do anything ( the buffers are clean ) .
2006-10-11 12:20:53 +04:00
* ext4_force_commit will write the file data into the journal and
2006-10-11 12:20:50 +04:00
* will wait on that .
* filemap_fdatawait ( ) will encounter a ton of newly - dirtied pages
* ( they were dirtied by commit ) . But that ' s OK - the blocks are
* safe in - journal , which is all fsync ( ) needs to ensure .
*/
2009-11-23 15:24:57 +03:00
if ( ext4_should_journal_data ( inode ) )
return ext4_force_commit ( inode - > i_sb ) ;
2006-10-11 12:20:50 +04:00
2009-12-09 07:51:10 +03:00
commit_tid = datasync ? ei - > i_datasync_tid : ei - > i_sync_tid ;
2009-12-23 14:52:08 +03:00
if ( jbd2_log_start_commit ( journal , commit_tid ) ) {
/*
* When the journal is on a different device than the
* fs data disk , we need to issue the barrier in
* writeback mode . ( In ordered mode , the jbd2 layer
* will take care of issuing the barrier . In
* data = journal , all of the data blocks are written to
* the journal device . )
*/
if ( ext4_should_writeback_data ( inode ) & &
( journal - > j_fs_dev ! = journal - > j_dev ) & &
( journal - > j_flags & JBD2_BARRIER ) )
blkdev_issue_flush ( inode - > i_sb - > s_bdev , NULL ) ;
2009-12-09 07:51:10 +03:00
jbd2_log_wait_commit ( journal , commit_tid ) ;
2009-12-23 14:52:08 +03:00
} else if ( journal - > j_flags & JBD2_BARRIER )
2009-09-06 05:42:42 +04:00
blkdev_issue_flush ( inode - > i_sb - > s_bdev , NULL ) ;
2006-10-11 12:20:50 +04:00
return ret ;
}