2005-04-17 02:20:36 +04:00
/*
* linux / fs / ext3 / fsync . c
*
* 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-09-27 12:49:27 +04:00
*
2005-04-17 02:20:36 +04:00
* ext3fs fsync primitive
*
* Big - endian to little - endian byte - swapping / bitmaps by
* David S . Miller ( davem @ caip . rutgers . edu ) , 1995
2006-09-27 12:49:27 +04:00
*
2005-04-17 02:20:36 +04:00
* Removed unnecessary code duplication for little endian machines
2006-09-27 12:49:27 +04:00
* and excessive __inline__s .
2005-04-17 02:20:36 +04:00
* 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>
2009-09-08 16:59:42 +04:00
# include <linux/blkdev.h>
2005-04-17 02:20:36 +04:00
# include <linux/fs.h>
# include <linux/sched.h>
# include <linux/writeback.h>
# include <linux/jbd.h>
# include <linux/ext3_fs.h>
# include <linux/ext3_jbd.h>
/*
* akpm : A new design for ext3_sync_file ( ) .
*
* 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 .
*/
int ext3_sync_file ( struct file * file , struct dentry * dentry , int datasync )
{
struct inode * inode = dentry - > d_inode ;
2009-10-16 21:26:15 +04:00
struct ext3_inode_info * ei = EXT3_I ( inode ) ;
journal_t * journal = EXT3_SB ( inode - > i_sb ) - > s_journal ;
2010-04-16 00:24:26 +04:00
int ret , needs_barrier = 0 ;
2009-10-16 21:26:15 +04:00
tid_t commit_tid ;
if ( inode - > i_sb - > s_flags & MS_RDONLY )
return 0 ;
2005-04-17 02:20:36 +04:00
2007-10-18 14:07:05 +04:00
J_ASSERT ( ext3_journal_current_handle ( ) = = NULL ) ;
2005-04-17 02:20:36 +04:00
/*
2009-10-16 21:26:15 +04:00
* data = writeback , ordered :
2005-04-17 02:20:36 +04:00
* The caller ' s filemap_fdatawrite ( ) / wait will sync the data .
2009-10-16 21:26:15 +04:00
* Metadata is in the journal , we wait for a proper transaction
* to commit here .
2005-04-17 02:20:36 +04:00
*
* data = journal :
* filemap_fdatawrite won ' t do anything ( the buffers are clean ) .
* ext3_force_commit will write the file data into the journal and
* 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 .
*/
2010-04-16 00:24:26 +04:00
if ( ext3_should_journal_data ( inode ) )
return ext3_force_commit ( inode - > i_sb ) ;
2005-04-17 02:20:36 +04:00
2009-10-16 21:26:15 +04:00
if ( datasync )
commit_tid = atomic_read ( & ei - > i_datasync_tid ) ;
else
commit_tid = atomic_read ( & ei - > i_sync_tid ) ;
2008-04-28 13:16:05 +04:00
2010-04-16 00:24:26 +04:00
if ( test_opt ( inode - > i_sb , BARRIER ) & &
! journal_trans_will_send_data_barrier ( journal , commit_tid ) )
needs_barrier = 1 ;
log_start_commit ( journal , commit_tid ) ;
ret = log_wait_commit ( journal , commit_tid ) ;
2009-10-16 21:26:15 +04:00
2009-09-08 16:59:42 +04:00
/*
* In case we didn ' t commit a transaction , we have to flush
* disk caches manually so that data really is on persistent
* storage
*/
2010-04-16 00:24:26 +04:00
if ( needs_barrier )
2010-04-28 17:55:06 +04:00
blkdev_issue_flush ( inode - > i_sb - > s_bdev , GFP_KERNEL , NULL ,
BLKDEV_IFL_WAIT ) ;
2005-04-17 02:20:36 +04:00
return ret ;
}