File: /usr/src/linux/fs/reiserfs/file.c

1     /*
2      * Copyright 2000 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     */
25     static 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_pack_on_close || 
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     
46     #ifdef REISERFS_PREALLOCATE
47         reiserfs_discard_prealloc (&th, inode);
48     #endif
49         journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3) ;
50     
51         if (atomic_read(&inode->i_count) <= 1 &&
52     	inode->u.reiserfs_i.i_pack_on_close &&
53             tail_has_to_be_packed (inode)) {
54     	/* if regular file is released by last holder and it has been
55     	   appended (we append by unformatted node only) or its direct
56     	   item(s) had to be converted, then it may have to be
57     	   indirect2direct converted */
58     	windex = push_journal_writer("file_release") ;
59     	reiserfs_truncate_file(inode, 0) ;
60     	pop_journal_writer(windex) ;
61         }
62         up (&inode->i_sem); 
63         unlock_kernel() ;
64         return 0;
65     }
66     
67     static void reiserfs_vfs_truncate_file(struct inode *inode) {
68         reiserfs_truncate_file(inode, 1) ;
69     }
70     
71     /* Sync a reiserfs file. */
72     static int reiserfs_sync_file(
73     			      struct file   * p_s_filp,
74     			      struct dentry * p_s_dentry,
75     			      int datasync
76     			      ) {
77       struct inode * p_s_inode = p_s_dentry->d_inode;
78       struct reiserfs_transaction_handle th ;
79       int n_err;
80       int windex ;
81       int jbegin_count = 1 ;
82     
83       lock_kernel() ;
84     
85       if (!S_ISREG(p_s_inode->i_mode))
86           BUG ();
87     
88       n_err = fsync_inode_buffers(p_s_inode) ;
89       n_err |= fsync_inode_data_buffers(p_s_inode);
90       /* commit the current transaction to flush any metadata
91       ** changes.  sys_fsync takes care of flushing the dirty pages for us
92       */
93       journal_begin(&th, p_s_inode->i_sb, jbegin_count) ;
94       windex = push_journal_writer("sync_file") ;
95       reiserfs_update_sd(&th, p_s_inode);
96       pop_journal_writer(windex) ;
97       journal_end_sync(&th, p_s_inode->i_sb,jbegin_count) ;
98       unlock_kernel() ;
99       return ( n_err < 0 ) ? -EIO : 0;
100     }
101     
102     static int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
103         struct inode *inode = dentry->d_inode ;
104         int error ;
105         if (attr->ia_valid & ATTR_SIZE) {
106     	/* version 2 items will be caught by the s_maxbytes check
107     	** done for us in vmtruncate
108     	*/
109             if (inode_items_version(inode) == ITEM_VERSION_1 && 
110     	    attr->ia_size > MAX_NON_LFS)
111                 return -EFBIG ;
112         }
113     
114         error = inode_change_ok(inode, attr) ;
115         if (!error)
116             inode_setattr(inode, attr) ;
117     
118         return error ;
119     }
120     
121     struct file_operations reiserfs_file_operations = {
122         read:	generic_file_read,
123         write:	generic_file_write,
124         ioctl:	reiserfs_ioctl,
125         mmap:	generic_file_mmap,
126         release:	reiserfs_file_release,
127         fsync:	reiserfs_sync_file,
128     };
129     
130     
131     struct  inode_operations reiserfs_file_inode_operations = {
132         truncate:	reiserfs_vfs_truncate_file,
133         setattr:    reiserfs_setattr,
134     };
135     
136     
137