2005-04-17 02:20:36 +04:00
/*
* Copyright 2000 by Hans Reiser , licensing governed by reiserfs / README
*/
# include <linux/time.h>
2012-03-17 09:16:43 +04:00
# include "reiserfs.h"
2012-03-17 09:03:10 +04:00
# include "acl.h"
2012-03-17 08:59:06 +04:00
# include "xattr.h"
2014-08-09 01:21:12 +04:00
# include <linux/uaccess.h>
2005-04-17 02:20:36 +04:00
# include <linux/pagemap.h>
# include <linux/swap.h>
# include <linux/writeback.h>
# include <linux/blkdev.h>
# include <linux/buffer_head.h>
# include <linux/quotaops.h>
/*
2014-04-23 18:00:36 +04:00
* We pack the tails of files on file close , not at the time they are written .
* This implies an unnecessary copy of the tail and an unnecessary indirect item
* insertion / balancing , for files that are written in one write .
* It avoids unnecessary tail packings ( balances ) for files that are written in
* multiple writes and are small enough to have tails .
*
* file_release is called by the VFS layer when the file is closed . If
* this is the last open file descriptor , and the file
* small enough to have a tail , and the tail is currently in an
* unformatted node , the tail is converted back into a direct item .
*
* We use reiserfs_truncate_file to pack the tail , since it already has
* all the conditions coded .
*/
2005-07-13 07:21:28 +04:00
static int reiserfs_file_release ( struct inode * inode , struct file * filp )
2005-04-17 02:20:36 +04:00
{
2005-07-13 07:21:28 +04:00
struct reiserfs_transaction_handle th ;
int err ;
int jbegin_failure = 0 ;
2005-04-17 02:20:36 +04:00
2006-10-04 01:36:38 +04:00
BUG_ON ( ! S_ISREG ( inode - > i_mode ) ) ;
2005-04-17 02:20:36 +04:00
2010-07-04 12:18:57 +04:00
if ( atomic_add_unless ( & REISERFS_I ( inode ) - > openers , - 1 , 1 ) )
return 0 ;
2014-04-23 18:00:42 +04:00
mutex_lock ( & REISERFS_I ( inode ) - > tailpack ) ;
2010-07-04 12:18:57 +04:00
if ( ! atomic_dec_and_test ( & REISERFS_I ( inode ) - > openers ) ) {
2014-04-23 18:00:42 +04:00
mutex_unlock ( & REISERFS_I ( inode ) - > tailpack ) ;
2010-07-04 12:18:57 +04:00
return 0 ;
}
2005-07-13 07:21:28 +04:00
/* fast out for when nothing needs to be done */
2010-07-04 12:18:57 +04:00
if ( ( ! ( REISERFS_I ( inode ) - > i_flags & i_pack_on_close_mask ) | |
2005-07-13 07:21:28 +04:00
! tail_has_to_be_packed ( inode ) ) & &
REISERFS_I ( inode ) - > i_prealloc_count < = 0 ) {
2014-04-23 18:00:42 +04:00
mutex_unlock ( & REISERFS_I ( inode ) - > tailpack ) ;
2005-07-13 07:21:28 +04:00
return 0 ;
}
2005-04-17 02:20:36 +04:00
2006-08-05 23:15:08 +04:00
reiserfs_write_lock ( inode - > i_sb ) ;
2014-04-23 18:00:36 +04:00
/*
* freeing preallocation only involves relogging blocks that
2005-07-13 07:21:28 +04:00
* are already in the current transaction . preallocation gets
* freed at the end of each transaction , so it is impossible for
* us to log any additional blocks ( including quota blocks )
*/
err = journal_begin ( & th , inode - > i_sb , 1 ) ;
2005-04-17 02:20:36 +04:00
if ( err ) {
2014-04-23 18:00:36 +04:00
/*
* uh oh , we can ' t allow the inode to go away while there
2005-07-13 07:21:28 +04:00
* is still preallocation blocks pending . Try to join the
* aborted transaction
*/
jbegin_failure = err ;
2014-04-23 18:00:40 +04:00
err = journal_join_abort ( & th , inode - > i_sb ) ;
2005-07-13 07:21:28 +04:00
if ( err ) {
2014-04-23 18:00:36 +04:00
/*
* hmpf , our choices here aren ' t good . We can pin
* the inode which will disallow unmount from ever
* happening , we can do nothing , which will corrupt
* random memory on unmount , or we can forcibly
* remove the file from the preallocation list , which
* will leak blocks on disk . Lets pin the inode
2005-07-13 07:21:28 +04:00
* and let the admin know what is going on .
*/
igrab ( inode ) ;
2009-03-30 22:02:21 +04:00
reiserfs_warning ( inode - > i_sb , " clm-9001 " ,
2005-07-13 07:21:28 +04:00
" pinning inode %lu because the "
2006-11-25 22:09:30 +03:00
" preallocation can't be freed " ,
inode - > i_ino ) ;
2005-07-13 07:21:28 +04:00
goto out ;
}
2005-04-17 02:20:36 +04:00
}
2005-07-13 07:21:28 +04:00
reiserfs_update_inode_transaction ( inode ) ;
2005-04-17 02:20:36 +04:00
# ifdef REISERFS_PREALLOCATE
2005-07-13 07:21:28 +04:00
reiserfs_discard_prealloc ( & th , inode ) ;
2005-04-17 02:20:36 +04:00
# endif
2014-04-23 18:00:38 +04:00
err = journal_end ( & th ) ;
2005-07-13 07:21:28 +04:00
/* copy back the error code from journal_begin */
if ( ! err )
err = jbegin_failure ;
2010-07-04 12:18:57 +04:00
if ( ! err & &
2005-07-13 07:21:28 +04:00
( REISERFS_I ( inode ) - > i_flags & i_pack_on_close_mask ) & &
tail_has_to_be_packed ( inode ) ) {
2010-07-04 12:18:57 +04:00
2014-04-23 18:00:36 +04:00
/*
* if regular file is released by last holder and it has been
* appended ( we append by unformatted node only ) or its direct
* item ( s ) had to be converted , then it may have to be
* indirect2direct converted
*/
2005-07-13 07:21:28 +04:00
err = reiserfs_truncate_file ( inode , 0 ) ;
}
2014-04-23 18:00:41 +04:00
out :
2005-07-13 07:21:28 +04:00
reiserfs_write_unlock ( inode - > i_sb ) ;
2014-04-23 18:00:42 +04:00
mutex_unlock ( & REISERFS_I ( inode ) - > tailpack ) ;
2005-07-13 07:21:28 +04:00
return err ;
2005-04-17 02:20:36 +04:00
}
2010-07-04 12:18:57 +04:00
static int reiserfs_file_open ( struct inode * inode , struct file * file )
2007-01-23 07:40:46 +03:00
{
2010-07-04 12:18:57 +04:00
int err = dquot_file_open ( inode , file ) ;
2014-04-23 18:00:36 +04:00
/* somebody might be tailpacking on final close; wait for it */
2010-07-04 12:18:57 +04:00
if ( ! atomic_inc_not_zero ( & REISERFS_I ( inode ) - > openers ) ) {
2014-04-23 18:00:42 +04:00
mutex_lock ( & REISERFS_I ( inode ) - > tailpack ) ;
2010-07-04 12:18:57 +04:00
atomic_inc ( & REISERFS_I ( inode ) - > openers ) ;
2014-04-23 18:00:42 +04:00
mutex_unlock ( & REISERFS_I ( inode ) - > tailpack ) ;
2010-07-04 12:18:57 +04:00
}
return err ;
2007-01-23 07:40:46 +03:00
}
2012-12-15 14:47:31 +04:00
void reiserfs_vfs_truncate_file ( struct inode * inode )
2005-07-13 07:21:28 +04:00
{
2014-04-23 18:00:42 +04:00
mutex_lock ( & REISERFS_I ( inode ) - > tailpack ) ;
2005-07-13 07:21:28 +04:00
reiserfs_truncate_file ( inode , 1 ) ;
2014-04-23 18:00:42 +04:00
mutex_unlock ( & REISERFS_I ( inode ) - > tailpack ) ;
2005-04-17 02:20:36 +04:00
}
/* Sync a reiserfs file. */
/*
* FIXME : sync_mapping_buffers ( ) never has anything to sync . Can
* be removed . . .
*/
2011-07-17 04:44:56 +04:00
static int reiserfs_sync_file ( struct file * filp , loff_t start , loff_t end ,
int datasync )
2005-07-13 07:21:28 +04:00
{
2010-05-26 19:53:25 +04:00
struct inode * inode = filp - > f_mapping - > host ;
2009-03-30 22:02:50 +04:00
int err ;
2005-07-13 07:21:28 +04:00
int barrier_done ;
2011-07-17 04:44:56 +04:00
err = filemap_write_and_wait_range ( inode - > i_mapping , start , end ) ;
if ( err )
return err ;
mutex_lock ( & inode - > i_mutex ) ;
2009-03-30 22:02:47 +04:00
BUG_ON ( ! S_ISREG ( inode - > i_mode ) ) ;
2009-03-30 22:02:50 +04:00
err = sync_mapping_buffers ( inode - > i_mapping ) ;
2009-03-30 22:02:47 +04:00
reiserfs_write_lock ( inode - > i_sb ) ;
barrier_done = reiserfs_commit_for_inode ( inode ) ;
reiserfs_write_unlock ( inode - > i_sb ) ;
if ( barrier_done ! = 1 & & reiserfs_barrier_flush ( inode - > i_sb ) )
2010-09-16 22:51:46 +04:00
blkdev_issue_flush ( inode - > i_sb - > s_bdev , GFP_KERNEL , NULL ) ;
2011-07-17 04:44:56 +04:00
mutex_unlock ( & inode - > i_mutex ) ;
2005-07-13 07:21:28 +04:00
if ( barrier_done < 0 )
return barrier_done ;
2009-03-30 22:02:50 +04:00
return ( err < 0 ) ? - EIO : 0 ;
2005-04-17 02:20:36 +04:00
}
/* taken fs/buffer.c:__block_commit_write */
int reiserfs_commit_page ( struct inode * inode , struct page * page ,
2005-07-13 07:21:28 +04:00
unsigned from , unsigned to )
2005-04-17 02:20:36 +04:00
{
2005-07-13 07:21:28 +04:00
unsigned block_start , block_end ;
int partial = 0 ;
unsigned blocksize ;
struct buffer_head * bh , * head ;
unsigned long i_size_index = inode - > i_size > > PAGE_CACHE_SHIFT ;
int new ;
int logit = reiserfs_file_data_log ( inode ) ;
struct super_block * s = inode - > i_sb ;
int bh_per_page = PAGE_CACHE_SIZE / s - > s_blocksize ;
struct reiserfs_transaction_handle th ;
int ret = 0 ;
th . t_trans_id = 0 ;
blocksize = 1 < < inode - > i_blkbits ;
if ( logit ) {
reiserfs_write_lock ( s ) ;
ret = journal_begin ( & th , s , bh_per_page + 1 ) ;
if ( ret )
goto drop_write_lock ;
reiserfs_update_inode_transaction ( inode ) ;
}
for ( bh = head = page_buffers ( page ) , block_start = 0 ;
bh ! = head | | ! block_start ;
block_start = block_end , bh = bh - > b_this_page ) {
new = buffer_new ( bh ) ;
clear_buffer_new ( bh ) ;
block_end = block_start + blocksize ;
if ( block_end < = from | | block_start > = to ) {
if ( ! buffer_uptodate ( bh ) )
partial = 1 ;
} else {
set_buffer_uptodate ( bh ) ;
if ( logit ) {
reiserfs_prepare_for_journal ( s , bh , 1 ) ;
2014-04-23 18:00:39 +04:00
journal_mark_dirty ( & th , bh ) ;
2005-07-13 07:21:28 +04:00
} else if ( ! buffer_dirty ( bh ) ) {
mark_buffer_dirty ( bh ) ;
2014-04-23 18:00:36 +04:00
/*
* do data = ordered on any page past the end
2005-07-13 07:21:28 +04:00
* of file and any buffer marked BH_New .
*/
if ( reiserfs_data_ordered ( inode - > i_sb ) & &
( new | | page - > index > = i_size_index ) ) {
reiserfs_add_ordered_list ( inode , bh ) ;
}
}
}
2005-04-17 02:20:36 +04:00
}
2005-07-13 07:21:28 +04:00
if ( logit ) {
2014-04-23 18:00:38 +04:00
ret = journal_end ( & th ) ;
2014-04-23 18:00:41 +04:00
drop_write_lock :
2005-07-13 07:21:28 +04:00
reiserfs_write_unlock ( s ) ;
}
/*
* If this is a partial write which happened to make all buffers
* uptodate then we can optimize away a bogus readpage ( ) for
* the next read ( ) . Here we ' discover ' whether the page went
* uptodate as a result of this ( potentially partial ) write .
*/
if ( ! partial )
SetPageUptodate ( page ) ;
return ret ;
2005-04-17 02:20:36 +04:00
}
2006-03-28 13:56:42 +04:00
const struct file_operations reiserfs_file_operations = {
2009-10-15 01:22:17 +04:00
. unlocked_ioctl = reiserfs_ioctl ,
2006-08-29 22:06:18 +04:00
# ifdef CONFIG_COMPAT
. compat_ioctl = reiserfs_compat_ioctl ,
# endif
2010-07-04 12:18:57 +04:00
. mmap = generic_file_mmap ,
. open = reiserfs_file_open ,
2005-07-13 07:21:28 +04:00
. release = reiserfs_file_release ,
. fsync = reiserfs_sync_file ,
2014-04-02 22:33:16 +04:00
. read_iter = generic_file_read_iter ,
2014-04-03 11:17:43 +04:00
. write_iter = generic_file_write_iter ,
2006-03-30 17:15:30 +04:00
. splice_read = generic_file_splice_read ,
2014-04-05 12:27:08 +04:00
. splice_write = iter_file_splice_write ,
2008-09-08 21:42:50 +04:00
. llseek = generic_file_llseek ,
2005-04-17 02:20:36 +04:00
} ;
2007-02-12 11:55:40 +03:00
const struct inode_operations reiserfs_file_inode_operations = {
2005-07-13 07:21:28 +04:00
. setattr = reiserfs_setattr ,
. setxattr = reiserfs_setxattr ,
. getxattr = reiserfs_getxattr ,
. listxattr = reiserfs_listxattr ,
. removexattr = reiserfs_removexattr ,
. permission = reiserfs_permission ,
2011-07-23 19:37:31 +04:00
. get_acl = reiserfs_get_acl ,
2013-12-20 17:16:49 +04:00
. set_acl = reiserfs_set_acl ,
2005-04-17 02:20:36 +04:00
} ;