2006-10-11 12:20:50 +04:00
/*
2006-10-11 12:20:53 +04:00
* linux / fs / ext4 / file . c
2006-10-11 12:20:50 +04:00
*
* Copyright ( C ) 1992 , 1993 , 1994 , 1995
* Remy Card ( card @ masi . ibp . fr )
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie ( Paris VI )
*
* from
*
* linux / fs / minix / file . c
*
* Copyright ( C ) 1991 , 1992 Linus Torvalds
*
2006-10-11 12:20:53 +04:00
* ext4 fs regular file handling primitives
2006-10-11 12:20:50 +04:00
*
* 64 - bit file support on 64 - bit platforms by Jakub Jelinek
* ( jj @ sunsite . ms . mff . cuni . cz )
*/
# include <linux/time.h>
# include <linux/fs.h>
2006-10-11 12:21:01 +04:00
# include <linux/jbd2.h>
2006-10-11 12:20:53 +04:00
# include <linux/ext4_fs.h>
2006-10-11 12:21:01 +04:00
# include <linux/ext4_jbd2.h>
2006-10-11 12:20:50 +04:00
# include "xattr.h"
# include "acl.h"
/*
* Called when an inode is released . Note that this is different
2006-10-11 12:20:53 +04:00
* from ext4_file_open : open gets called at every open , but release
2006-10-11 12:20:50 +04:00
* gets called only when / all / the files are closed .
*/
2006-10-11 12:20:53 +04:00
static int ext4_release_file ( struct inode * inode , struct file * filp )
2006-10-11 12:20:50 +04:00
{
/* if we are the last writer on the inode, drop the block reservation */
if ( ( filp - > f_mode & FMODE_WRITE ) & &
( atomic_read ( & inode - > i_writecount ) = = 1 ) )
{
2006-10-11 12:20:53 +04:00
mutex_lock ( & EXT4_I ( inode ) - > truncate_mutex ) ;
ext4_discard_reservation ( inode ) ;
mutex_unlock ( & EXT4_I ( inode ) - > truncate_mutex ) ;
2006-10-11 12:20:50 +04:00
}
if ( is_dx ( inode ) & & filp - > private_data )
2006-10-11 12:20:53 +04:00
ext4_htree_free_dir_info ( filp - > private_data ) ;
2006-10-11 12:20:50 +04:00
return 0 ;
}
static ssize_t
2006-10-11 12:20:53 +04:00
ext4_file_write ( struct kiocb * iocb , const struct iovec * iov ,
2006-10-11 12:20:50 +04:00
unsigned long nr_segs , loff_t pos )
{
struct file * file = iocb - > ki_filp ;
struct inode * inode = file - > f_dentry - > d_inode ;
ssize_t ret ;
int err ;
ret = generic_file_aio_write ( iocb , iov , nr_segs , pos ) ;
/*
* Skip flushing if there was an error , or if nothing was written .
*/
if ( ret < = 0 )
return ret ;
/*
* If the inode is IS_SYNC , or is O_SYNC and we are doing data
* journalling then we need to make sure that we force the transaction
* to disk to keep all metadata uptodate synchronously .
*/
if ( file - > f_flags & O_SYNC ) {
/*
* If we are non - data - journaled , then the dirty data has
* already been flushed to backing store by generic_osync_inode ,
* and the inode has been flushed too if there have been any
* modifications other than mere timestamp updates .
*
* Open question - - - do we care about flushing timestamps too
* if the inode is IS_SYNC ?
*/
2006-10-11 12:20:53 +04:00
if ( ! ext4_should_journal_data ( inode ) )
2006-10-11 12:20:50 +04:00
return ret ;
goto force_commit ;
}
/*
* So we know that there has been no forced data flush . If the inode
* is marked IS_SYNC , we need to force one ourselves .
*/
if ( ! IS_SYNC ( inode ) )
return ret ;
/*
* Open question # 2 - - - should we force data to disk here too ? If we
* don ' t , the only impact is that data = writeback filesystems won ' t
* flush data to disk automatically on IS_SYNC , only metadata ( but
* historically , that is what ext2 has done . )
*/
force_commit :
2006-10-11 12:20:53 +04:00
err = ext4_force_commit ( inode - > i_sb ) ;
2006-10-11 12:20:50 +04:00
if ( err )
return err ;
return ret ;
}
2006-10-11 12:20:53 +04:00
const struct file_operations ext4_file_operations = {
2006-10-11 12:20:50 +04:00
. llseek = generic_file_llseek ,
. read = do_sync_read ,
. write = do_sync_write ,
. aio_read = generic_file_aio_read ,
2006-10-11 12:20:53 +04:00
. aio_write = ext4_file_write ,
. ioctl = ext4_ioctl ,
2006-10-11 12:20:50 +04:00
# ifdef CONFIG_COMPAT
2006-10-11 12:20:53 +04:00
. compat_ioctl = ext4_compat_ioctl ,
2006-10-11 12:20:50 +04:00
# endif
. mmap = generic_file_mmap ,
. open = generic_file_open ,
2006-10-11 12:20:53 +04:00
. release = ext4_release_file ,
. fsync = ext4_sync_file ,
2006-10-11 12:20:50 +04:00
. sendfile = generic_file_sendfile ,
. splice_read = generic_file_splice_read ,
. splice_write = generic_file_splice_write ,
} ;
2006-10-11 12:20:53 +04:00
struct inode_operations ext4_file_inode_operations = {
. truncate = ext4_truncate ,
. setattr = ext4_setattr ,
# ifdef CONFIG_EXT4DEV_FS_XATTR
2006-10-11 12:20:50 +04:00
. setxattr = generic_setxattr ,
. getxattr = generic_getxattr ,
2006-10-11 12:20:53 +04:00
. listxattr = ext4_listxattr ,
2006-10-11 12:20:50 +04:00
. removexattr = generic_removexattr ,
# endif
2006-10-11 12:20:53 +04:00
. permission = ext4_permission ,
2006-10-11 12:20:50 +04:00
} ;