2005-04-16 15:20:36 -07:00
/*
2005-11-02 14:58:39 +11:00
* Copyright ( c ) 2000 - 2005 Silicon Graphics , Inc .
* All Rights Reserved .
2005-04-16 15:20:36 -07:00
*
2005-11-02 14:58:39 +11:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
2005-04-16 15:20:36 -07:00
* published by the Free Software Foundation .
*
2005-11-02 14:58:39 +11:00
* This program is distributed in the hope that it would be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2005-04-16 15:20:36 -07:00
*
2005-11-02 14:58:39 +11:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
2005-04-16 15:20:36 -07:00
*/
# include "xfs.h"
2005-11-02 14:38:42 +11:00
# include "xfs_bit.h"
2005-04-16 15:20:36 -07:00
# include "xfs_log.h"
2005-11-02 14:38:42 +11:00
# include "xfs_inum.h"
2005-04-16 15:20:36 -07:00
# include "xfs_sb.h"
2005-11-02 14:38:42 +11:00
# include "xfs_ag.h"
2005-04-16 15:20:36 -07:00
# include "xfs_dir2.h"
# include "xfs_trans.h"
# include "xfs_dmapi.h"
# include "xfs_mount.h"
# include "xfs_bmap_btree.h"
# include "xfs_alloc_btree.h"
# include "xfs_ialloc_btree.h"
# include "xfs_alloc.h"
# include "xfs_btree.h"
# include "xfs_attr_sf.h"
# include "xfs_dir2_sf.h"
# include "xfs_dinode.h"
# include "xfs_inode.h"
# include "xfs_error.h"
# include "xfs_rw.h"
2007-08-29 10:58:01 +10:00
# include "xfs_vnodeops.h"
2008-11-28 14:23:32 +11:00
# include "xfs_da_btree.h"
2008-12-03 07:55:34 -05:00
# include "xfs_ioctl.h"
2005-04-16 15:20:36 -07:00
# include <linux/dcache.h>
# include <linux/smp_lock.h>
2006-03-14 14:00:35 +11:00
static struct vm_operations_struct xfs_file_vm_ops ;
2005-04-16 15:20:36 -07:00
2008-12-09 04:47:33 -05:00
STATIC ssize_t
xfs_file_aio_read (
2005-04-16 15:20:36 -07:00
struct kiocb * iocb ,
2006-09-30 23:28:46 -07:00
const struct iovec * iov ,
unsigned long nr_segs ,
2005-04-16 15:20:36 -07:00
loff_t pos )
{
struct file * file = iocb - > ki_filp ;
2008-12-09 04:47:33 -05:00
int ioflags = IO_ISAIO ;
2005-04-16 15:20:36 -07:00
BUG_ON ( iocb - > ki_pos ! = pos ) ;
if ( unlikely ( file - > f_flags & O_DIRECT ) )
ioflags | = IO_ISDIRECT ;
2008-12-09 04:47:33 -05:00
if ( file - > f_mode & FMODE_NOCMTIME )
ioflags | = IO_INVIS ;
2007-08-29 10:58:01 +10:00
return xfs_read ( XFS_I ( file - > f_path . dentry - > d_inode ) , iocb , iov ,
nr_segs , & iocb - > ki_pos , ioflags ) ;
2005-04-16 15:20:36 -07:00
}
STATIC ssize_t
2008-12-09 04:47:33 -05:00
xfs_file_aio_write (
2006-09-30 23:28:46 -07:00
struct kiocb * iocb ,
const struct iovec * iov ,
unsigned long nr_segs ,
loff_t pos )
2005-04-16 15:20:36 -07:00
{
2008-12-09 04:47:33 -05:00
struct file * file = iocb - > ki_filp ;
int ioflags = IO_ISAIO ;
2005-04-16 15:20:36 -07:00
BUG_ON ( iocb - > ki_pos ! = pos ) ;
if ( unlikely ( file - > f_flags & O_DIRECT ) )
ioflags | = IO_ISDIRECT ;
2008-12-09 04:47:33 -05:00
if ( file - > f_mode & FMODE_NOCMTIME )
ioflags | = IO_INVIS ;
2007-08-29 10:58:01 +10:00
return xfs_write ( XFS_I ( file - > f_mapping - > host ) , iocb , iov , nr_segs ,
& iocb - > ki_pos , ioflags ) ;
2005-04-16 15:20:36 -07:00
}
2006-03-31 13:08:59 +10:00
STATIC ssize_t
xfs_file_splice_read (
struct file * infilp ,
2006-04-11 14:57:50 +02:00
loff_t * ppos ,
2006-04-10 15:18:35 +02:00
struct pipe_inode_info * pipe ,
2006-03-31 13:08:59 +10:00
size_t len ,
unsigned int flags )
{
2008-12-09 04:47:33 -05:00
int ioflags = 0 ;
if ( infilp - > f_mode & FMODE_NOCMTIME )
ioflags | = IO_INVIS ;
2006-03-31 13:08:59 +10:00
2007-08-29 10:58:01 +10:00
return xfs_splice_read ( XFS_I ( infilp - > f_path . dentry - > d_inode ) ,
2008-12-09 04:47:33 -05:00
infilp , ppos , pipe , len , flags , ioflags ) ;
2006-03-31 13:08:59 +10:00
}
STATIC ssize_t
xfs_file_splice_write (
2006-04-10 15:18:35 +02:00
struct pipe_inode_info * pipe ,
2006-03-31 13:08:59 +10:00
struct file * outfilp ,
2006-04-11 14:57:50 +02:00
loff_t * ppos ,
2006-03-31 13:08:59 +10:00
size_t len ,
unsigned int flags )
{
2008-12-09 04:47:33 -05:00
int ioflags = 0 ;
if ( outfilp - > f_mode & FMODE_NOCMTIME )
ioflags | = IO_INVIS ;
2006-03-31 13:08:59 +10:00
2007-08-29 10:58:01 +10:00
return xfs_splice_write ( XFS_I ( outfilp - > f_path . dentry - > d_inode ) ,
2008-12-09 04:47:33 -05:00
pipe , outfilp , ppos , len , flags , ioflags ) ;
2006-03-31 13:08:59 +10:00
}
2005-04-16 15:20:36 -07:00
STATIC int
2006-03-14 14:00:35 +11:00
xfs_file_open (
2005-04-16 15:20:36 -07:00
struct inode * inode ,
2008-11-28 14:23:32 +11:00
struct file * file )
2005-04-16 15:20:36 -07:00
{
2008-11-28 14:23:32 +11:00
if ( ! ( file - > f_flags & O_LARGEFILE ) & & i_size_read ( inode ) > MAX_NON_LFS )
2005-04-16 15:20:36 -07:00
return - EFBIG ;
2008-11-28 14:23:32 +11:00
if ( XFS_FORCED_SHUTDOWN ( XFS_M ( inode - > i_sb ) ) )
return - EIO ;
return 0 ;
}
STATIC int
xfs_dir_open (
struct inode * inode ,
struct file * file )
{
struct xfs_inode * ip = XFS_I ( inode ) ;
int mode ;
int error ;
error = xfs_file_open ( inode , file ) ;
if ( error )
return error ;
/*
* If there are any blocks , read - ahead block 0 as we ' re almost
* certain to have the next operation be a read there .
*/
mode = xfs_ilock_map_shared ( ip ) ;
if ( ip - > i_d . di_nextents > 0 )
xfs_da_reada_buf ( NULL , ip , 0 , XFS_DATA_FORK ) ;
xfs_iunlock ( ip , mode ) ;
return 0 ;
2005-04-16 15:20:36 -07:00
}
STATIC int
2006-03-14 14:00:35 +11:00
xfs_file_release (
2005-04-16 15:20:36 -07:00
struct inode * inode ,
struct file * filp )
{
2007-08-29 10:58:01 +10:00
return - xfs_release ( XFS_I ( inode ) ) ;
2005-04-16 15:20:36 -07:00
}
2008-05-19 16:29:46 +10:00
/*
* We ignore the datasync flag here because a datasync is effectively
* identical to an fsync . That is , datasync implies that we need to write
* only the metadata needed to be able to access the data that is written
* if we crash after the call completes . Hence if we are writing beyond
* EOF we have to log the inode size change as well , which makes it a
* full fsync . If we don ' t write beyond EOF , the inode core will be
* clean in memory and so we don ' t need to log the inode , just like
* fsync .
*/
2005-04-16 15:20:36 -07:00
STATIC int
2006-03-14 14:00:35 +11:00
xfs_file_fsync (
2005-04-16 15:20:36 -07:00
struct file * filp ,
struct dentry * dentry ,
int datasync )
{
2007-08-29 11:44:37 +10:00
xfs_iflags_clear ( XFS_I ( dentry - > d_inode ) , XFS_ITRUNCATED ) ;
2008-05-19 16:29:46 +10:00
return - xfs_fsync ( XFS_I ( dentry - > d_inode ) ) ;
2005-04-16 15:20:36 -07:00
}
STATIC int
2006-03-14 14:00:35 +11:00
xfs_file_readdir (
2005-04-16 15:20:36 -07:00
struct file * filp ,
void * dirent ,
filldir_t filldir )
{
2007-08-28 13:58:24 +10:00
struct inode * inode = filp - > f_path . dentry - > d_inode ;
2007-08-29 10:58:01 +10:00
xfs_inode_t * ip = XFS_I ( inode ) ;
2007-08-28 13:58:24 +10:00
int error ;
size_t bufsize ;
/*
* The Linux API doesn ' t pass down the total size of the buffer
* we read into down to the filesystem . With the filldir concept
* it ' s not needed for correct information , but the XFS dir2 leaf
* code wants an estimate of the buffer size to calculate it ' s
* readahead window and size the buffers used for mapping to
* physical blocks .
*
* Try to give it an estimate that ' s good enough , maybe at some
* point we can change the - > readdir prototype to include the
* buffer size .
*/
2008-12-22 17:50:56 +11:00
bufsize = ( size_t ) min_t ( loff_t , PAGE_SIZE , ip - > i_d . di_size ) ;
2007-08-28 13:58:24 +10:00
2007-08-29 10:58:01 +10:00
error = xfs_readdir ( ip , dirent , bufsize ,
2007-08-28 13:58:24 +10:00
( xfs_off_t * ) & filp - > f_pos , filldir ) ;
if ( error )
return - error ;
return 0 ;
2005-04-16 15:20:36 -07:00
}
STATIC int
2006-03-14 14:00:35 +11:00
xfs_file_mmap (
2005-04-16 15:20:36 -07:00
struct file * filp ,
struct vm_area_struct * vma )
{
2006-03-14 14:00:35 +11:00
vma - > vm_ops = & xfs_file_vm_ops ;
2007-07-19 01:47:03 -07:00
vma - > vm_flags | = VM_CAN_NONLINEAR ;
2005-06-21 14:07:45 +10:00
2006-06-09 14:52:13 +10:00
file_accessed ( filp ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2007-07-19 16:28:17 +10:00
/*
* mmap ( ) d file has taken write protection fault and is being made
* writable . We can set the page state up correctly for a writable
* page , which means we can do correct delalloc accounting ( ENOSPC
* checking ! ) and unwritten extent mapping .
*/
STATIC int
xfs_vm_page_mkwrite (
struct vm_area_struct * vma ,
struct page * page )
{
return block_page_mkwrite ( vma , page , xfs_get_blocks ) ;
}
2006-03-28 01:56:42 -08:00
const struct file_operations xfs_file_operations = {
2005-04-16 15:20:36 -07:00
. llseek = generic_file_llseek ,
. read = do_sync_read ,
2005-09-02 15:43:05 +10:00
. write = do_sync_write ,
2006-03-14 14:00:35 +11:00
. aio_read = xfs_file_aio_read ,
. aio_write = xfs_file_aio_write ,
2006-03-31 13:08:59 +10:00
. splice_read = xfs_file_splice_read ,
. splice_write = xfs_file_splice_write ,
2006-03-14 14:00:35 +11:00
. unlocked_ioctl = xfs_file_ioctl ,
2005-04-16 15:20:36 -07:00
# ifdef CONFIG_COMPAT
2006-03-14 14:00:35 +11:00
. compat_ioctl = xfs_file_compat_ioctl ,
2005-04-16 15:20:36 -07:00
# endif
2006-03-14 14:00:35 +11:00
. mmap = xfs_file_mmap ,
. open = xfs_file_open ,
. release = xfs_file_release ,
. fsync = xfs_file_fsync ,
2005-04-16 15:20:36 -07:00
# ifdef HAVE_FOP_OPEN_EXEC
2006-03-14 14:00:35 +11:00
. open_exec = xfs_file_open_exec ,
2005-04-16 15:20:36 -07:00
# endif
} ;
2006-03-28 01:56:42 -08:00
const struct file_operations xfs_dir_file_operations = {
2008-11-28 14:23:32 +11:00
. open = xfs_dir_open ,
2005-04-16 15:20:36 -07:00
. read = generic_read_dir ,
2006-03-14 14:00:35 +11:00
. readdir = xfs_file_readdir ,
2008-08-24 07:24:41 -04:00
. llseek = generic_file_llseek ,
2006-03-14 14:00:35 +11:00
. unlocked_ioctl = xfs_file_ioctl ,
2005-05-06 06:44:46 -07:00
# ifdef CONFIG_COMPAT
2006-03-14 14:00:35 +11:00
. compat_ioctl = xfs_file_compat_ioctl ,
2005-05-06 06:44:46 -07:00
# endif
2006-03-14 14:00:35 +11:00
. fsync = xfs_file_fsync ,
2005-04-16 15:20:36 -07:00
} ;
2006-03-14 14:00:35 +11:00
static struct vm_operations_struct xfs_file_vm_ops = {
2007-07-19 01:46:59 -07:00
. fault = filemap_fault ,
2007-07-19 16:28:17 +10:00
. page_mkwrite = xfs_vm_page_mkwrite ,
2005-06-21 14:07:45 +10:00
} ;