1/* 2 * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README 3 */ 4 5 6#include <linux/sched.h> 7#include <linux/reiserfs_fs.h> 8#include <linux/smp_lock.h> 9 10/* 11** We pack the tails of files on file close, not at the time they are written. 12** This implies an unnecessary copy of the tail and an unnecessary indirect item 13** insertion/balancing, for files that are written in one write. 14** It avoids unnecessary tail packings (balances) for files that are written in 15** multiple writes and are small enough to have tails. 16** 17** file_release is called by the VFS layer when the file is closed. If 18** this is the last open file descriptor, and the file 19** small enough to have a tail, and the tail is currently in an 20** unformatted node, the tail is converted back into a direct item. 21** 22** We use reiserfs_truncate_file to pack the tail, since it already has 23** all the conditions coded. 24*/ 25static int reiserfs_file_release (struct inode * inode, struct file * filp) 26{ 27 28 struct reiserfs_transaction_handle th ; 29 int windex ; 30 31 if (!S_ISREG (inode->i_mode)) 32 BUG (); 33 34 /* fast out for when nothing needs to be done */ 35 if ((atomic_read(&inode->i_count) > 1 || 36 !(inode->u.reiserfs_i.i_flags & i_pack_on_close_mask) || 37 !tail_has_to_be_packed(inode)) && 38 inode->u.reiserfs_i.i_prealloc_count <= 0) { 39 return 0; 40 } 41 42 lock_kernel() ; 43 down (&inode->i_sem); 44 journal_begin(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3) ; 45 reiserfs_update_inode_transaction(inode) ; 46 47#ifdef REISERFS_PREALLOCATE 48 reiserfs_discard_prealloc (&th, inode); 49#endif 50 journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3) ; 51 52 if (atomic_read(&inode->i_count) <= 1 && 53 (inode->u.reiserfs_i.i_flags & i_pack_on_close_mask) && 54 tail_has_to_be_packed (inode)) { 55 /* if regular file is released by last holder and it has been 56 appended (we append by unformatted node only) or its direct 57 item(s) had to be converted, then it may have to be 58 indirect2direct converted */ 59 windex = push_journal_writer("file_release") ; 60 reiserfs_truncate_file(inode, 0) ; 61 pop_journal_writer(windex) ; 62 } 63 up (&inode->i_sem); 64 unlock_kernel() ; 65 return 0; 66} 67 68static void reiserfs_vfs_truncate_file(struct inode *inode) { 69 reiserfs_truncate_file(inode, 1) ; 70} 71 72/* Sync a reiserfs file. */ 73static int reiserfs_sync_file( 74 struct file * p_s_filp, 75 struct dentry * p_s_dentry, 76 int datasync 77 ) { 78 struct inode * p_s_inode = p_s_dentry->d_inode; 79 int n_err; 80 81 lock_kernel() ; 82 83 if (!S_ISREG(p_s_inode->i_mode)) 84 BUG (); 85 86 n_err = fsync_inode_buffers(p_s_inode) ; 87 n_err |= fsync_inode_data_buffers(p_s_inode); 88 reiserfs_commit_for_inode(p_s_inode) ; 89 unlock_kernel() ; 90 return ( n_err < 0 ) ? -EIO : 0; 91} 92 93static int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) { 94 struct inode *inode = dentry->d_inode ; 95 int error ; 96 if (attr->ia_valid & ATTR_SIZE) { 97 /* version 2 items will be caught by the s_maxbytes check 98 ** done for us in vmtruncate 99 */ 100 if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 && 101 attr->ia_size > MAX_NON_LFS) 102 return -EFBIG ; 103 104 /* fill in hole pointers in the expanding truncate case. */ 105 if (attr->ia_size > inode->i_size) { 106 error = generic_cont_expand(inode, attr->ia_size) ; 107 if (inode->u.reiserfs_i.i_prealloc_count > 0) { 108 struct reiserfs_transaction_handle th ; 109 /* we're changing at most 2 bitmaps, inode + super */ 110 journal_begin(&th, inode->i_sb, 4) ; 111 reiserfs_discard_prealloc (&th, inode); 112 journal_end(&th, inode->i_sb, 4) ; 113 } 114 if (error) 115 return error ; 116 } 117 } 118 119 if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) || 120 ((attr->ia_valid & ATTR_GID) && (attr->ia_gid & ~0xffff))) && 121 (get_inode_sd_version (inode) == STAT_DATA_V1)) 122 /* stat data of format v3.5 has 16 bit uid and gid */ 123 return -EINVAL; 124 125 error = inode_change_ok(inode, attr) ; 126 if (!error) 127 inode_setattr(inode, attr) ; 128 129 return error ; 130} 131 132struct file_operations reiserfs_file_operations = { 133 read: generic_file_read, 134 write: generic_file_write, 135 ioctl: reiserfs_ioctl, 136 mmap: generic_file_mmap, 137 release: reiserfs_file_release, 138 fsync: reiserfs_sync_file, 139}; 140 141 142struct inode_operations reiserfs_file_inode_operations = { 143 truncate: reiserfs_vfs_truncate_file, 144 setattr: reiserfs_setattr, 145}; 146 147 148