Blame view

fs/reiserfs/file.c 7.62 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
  #include <linux/time.h>
f466c6fdb   Al Viro   move private bits...
5
  #include "reiserfs.h"
a3063ab88   Al Viro   move reiserfs_acl...
6
  #include "acl.h"
c45ac8887   Al Viro   take private bits...
7
  #include "xattr.h"
17093991a   Fabian Frederick   fs/reiserfs: use ...
8
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
  #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>
  
  /*
098297b27   Jeff Mahoney   reiserfs: cleanup...
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   * 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.
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
31
  static int reiserfs_file_release(struct inode *inode, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
33
34
35
  	struct reiserfs_transaction_handle th;
  	int err;
  	int jbegin_failure = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36

14a61442c   Eric Sesterhenn   BUG_ON conversion...
37
  	BUG_ON(!S_ISREG(inode->i_mode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

0e4f6a791   Al Viro   Fix reiserfs_file...
39
40
          if (atomic_add_unless(&REISERFS_I(inode)->openers, -1, 1))
  		return 0;
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
41
  	mutex_lock(&REISERFS_I(inode)->tailpack);
0e4f6a791   Al Viro   Fix reiserfs_file...
42
43
  
          if (!atomic_dec_and_test(&REISERFS_I(inode)->openers)) {
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
44
  		mutex_unlock(&REISERFS_I(inode)->tailpack);
0e4f6a791   Al Viro   Fix reiserfs_file...
45
46
  		return 0;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
47
  	/* fast out for when nothing needs to be done */
0e4f6a791   Al Viro   Fix reiserfs_file...
48
  	if ((!(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) ||
bd4c625c0   Linus Torvalds   reiserfs: run scr...
49
50
  	     !tail_has_to_be_packed(inode)) &&
  	    REISERFS_I(inode)->i_prealloc_count <= 0) {
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
51
  		mutex_unlock(&REISERFS_I(inode)->tailpack);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
52
53
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54

b5f3953c1   Chris Mason   [PATCH] fix reise...
55
  	reiserfs_write_lock(inode->i_sb);
098297b27   Jeff Mahoney   reiserfs: cleanup...
56
57
  	/*
  	 * freeing preallocation only involves relogging blocks that
bd4c625c0   Linus Torvalds   reiserfs: run scr...
58
59
60
61
62
  	 * 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);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
  	if (err) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
64
65
  		/*
  		 * uh oh, we can't allow the inode to go away while there
bd4c625c0   Linus Torvalds   reiserfs: run scr...
66
67
68
69
  		 * is still preallocation blocks pending.  Try to join the
  		 * aborted transaction
  		 */
  		jbegin_failure = err;
b491dd176   Jeff Mahoney   reiserfs: cleanup...
70
  		err = journal_join_abort(&th, inode->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
71
72
  
  		if (err) {
098297b27   Jeff Mahoney   reiserfs: cleanup...
73
74
75
76
77
78
79
  			/*
  			 * 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
bd4c625c0   Linus Torvalds   reiserfs: run scr...
80
81
82
  			 * and let the admin know what is going on.
  			 */
  			igrab(inode);
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
83
  			reiserfs_warning(inode->i_sb, "clm-9001",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
84
  					 "pinning inode %lu because the "
533221fba   Alexey Dobriyan   [PATCH] reiserfs:...
85
86
  					 "preallocation can't be freed",
  					 inode->i_ino);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
87
88
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
90
  	reiserfs_update_inode_transaction(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
  
  #ifdef REISERFS_PREALLOCATE
bd4c625c0   Linus Torvalds   reiserfs: run scr...
93
  	reiserfs_discard_prealloc(&th, inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  #endif
58d854265   Jeff Mahoney   reiserfs: cleanup...
95
  	err = journal_end(&th);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
96
97
98
99
  
  	/* copy back the error code from journal_begin */
  	if (!err)
  		err = jbegin_failure;
0e4f6a791   Al Viro   Fix reiserfs_file...
100
  	if (!err &&
bd4c625c0   Linus Torvalds   reiserfs: run scr...
101
102
  	    (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) &&
  	    tail_has_to_be_packed(inode)) {
0e4f6a791   Al Viro   Fix reiserfs_file...
103

098297b27   Jeff Mahoney   reiserfs: cleanup...
104
105
106
107
108
109
  		/*
  		 * 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
  		 */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
110
111
  		err = reiserfs_truncate_file(inode, 0);
  	}
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
112
  out:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
113
  	reiserfs_write_unlock(inode->i_sb);
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
114
  	mutex_unlock(&REISERFS_I(inode)->tailpack);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
115
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
  }
0e4f6a791   Al Viro   Fix reiserfs_file...
117
  static int reiserfs_file_open(struct inode *inode, struct file *file)
de14569f9   Vladimir Saveliev   [PATCH] resierfs:...
118
  {
0e4f6a791   Al Viro   Fix reiserfs_file...
119
  	int err = dquot_file_open(inode, file);
098297b27   Jeff Mahoney   reiserfs: cleanup...
120
121
  
  	/* somebody might be tailpacking on final close; wait for it */
0e4f6a791   Al Viro   Fix reiserfs_file...
122
          if (!atomic_inc_not_zero(&REISERFS_I(inode)->openers)) {
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
123
  		mutex_lock(&REISERFS_I(inode)->tailpack);
0e4f6a791   Al Viro   Fix reiserfs_file...
124
  		atomic_inc(&REISERFS_I(inode)->openers);
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
125
  		mutex_unlock(&REISERFS_I(inode)->tailpack);
0e4f6a791   Al Viro   Fix reiserfs_file...
126
127
  	}
  	return err;
de14569f9   Vladimir Saveliev   [PATCH] resierfs:...
128
  }
cfac4b47c   Marco Stornelli   reiserfs: drop vm...
129
  void reiserfs_vfs_truncate_file(struct inode *inode)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
130
  {
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
131
  	mutex_lock(&REISERFS_I(inode)->tailpack);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
132
  	reiserfs_truncate_file(inode, 1);
a228bf8f0   Jeff Mahoney   reiserfs: cleanup...
133
  	mutex_unlock(&REISERFS_I(inode)->tailpack);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
136
137
138
139
140
141
  }
  
  /* Sync a reiserfs file. */
  
  /*
   * FIXME: sync_mapping_buffers() never has anything to sync.  Can
   * be removed...
   */
02c24a821   Josef Bacik   fs: push i_mutex ...
142
143
  static int reiserfs_sync_file(struct file *filp, loff_t start, loff_t end,
  			      int datasync)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
144
  {
7ea808591   Christoph Hellwig   drop unused dentr...
145
  	struct inode *inode = filp->f_mapping->host;
ee93961be   Jeff Mahoney   reiserfs: rename ...
146
  	int err;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
147
  	int barrier_done;
02c24a821   Josef Bacik   fs: push i_mutex ...
148
149
150
  	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
  	if (err)
  		return err;
5955102c9   Al Viro   wrappers for ->i_...
151
  	inode_lock(inode);
995c762ea   Jeff Mahoney   reiserfs: rename ...
152
  	BUG_ON(!S_ISREG(inode->i_mode));
ee93961be   Jeff Mahoney   reiserfs: rename ...
153
  	err = sync_mapping_buffers(inode->i_mapping);
995c762ea   Jeff Mahoney   reiserfs: rename ...
154
155
156
157
  	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))
dd3932edd   Christoph Hellwig   block: remove BLK...
158
  		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
5955102c9   Al Viro   wrappers for ->i_...
159
  	inode_unlock(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
160
161
  	if (barrier_done < 0)
  		return barrier_done;
ee93961be   Jeff Mahoney   reiserfs: rename ...
162
  	return (err < 0) ? -EIO : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
  /* taken fs/buffer.c:__block_commit_write */
  int reiserfs_commit_page(struct inode *inode, struct page *page,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
166
  			 unsigned from, unsigned to)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
168
169
170
171
  	unsigned block_start, block_end;
  	int partial = 0;
  	unsigned blocksize;
  	struct buffer_head *bh, *head;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
172
  	unsigned long i_size_index = inode->i_size >> PAGE_SHIFT;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
173
174
175
  	int new;
  	int logit = reiserfs_file_data_log(inode);
  	struct super_block *s = inode->i_sb;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
176
  	int bh_per_page = PAGE_SIZE / s->s_blocksize;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
  	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);
09f1b80ba   Jeff Mahoney   reiserfs: cleanup...
204
  				journal_mark_dirty(&th, bh);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
205
206
  			} else if (!buffer_dirty(bh)) {
  				mark_buffer_dirty(bh);
098297b27   Jeff Mahoney   reiserfs: cleanup...
207
208
  				/*
  				 * do data=ordered on any page past the end
bd4c625c0   Linus Torvalds   reiserfs: run scr...
209
210
211
212
213
214
215
216
  				 * 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);
  				}
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
218
  	if (logit) {
58d854265   Jeff Mahoney   reiserfs: cleanup...
219
  		ret = journal_end(&th);
cf776a7a4   Jeff Mahoney   reiserfs: cleanup...
220
  drop_write_lock:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
221
222
223
224
225
226
227
228
229
230
231
  		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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
  }
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
233
  const struct file_operations reiserfs_file_operations = {
205cb37b8   Frederic Weisbecker   kill-the-bkl/reis...
234
  	.unlocked_ioctl = reiserfs_ioctl,
52b499c43   David Howells   [PATCH] BLOCK: Mo...
235
236
237
  #ifdef CONFIG_COMPAT
  	.compat_ioctl = reiserfs_compat_ioctl,
  #endif
0e4f6a791   Al Viro   Fix reiserfs_file...
238
239
  	.mmap = generic_file_mmap,
  	.open = reiserfs_file_open,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
240
241
  	.release = reiserfs_file_release,
  	.fsync = reiserfs_sync_file,
aad4f8bb4   Al Viro   switch simple gen...
242
  	.read_iter = generic_file_read_iter,
8174202b3   Al Viro   write_iter varian...
243
  	.write_iter = generic_file_write_iter,
5274f052e   Jens Axboe   [PATCH] Introduce...
244
  	.splice_read = generic_file_splice_read,
8d0207652   Al Viro   ->splice_write() ...
245
  	.splice_write = iter_file_splice_write,
91efc167d   Christoph Hellwig   [PATCH] reiserfs:...
246
  	.llseek = generic_file_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  };
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
248
  const struct inode_operations reiserfs_file_inode_operations = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
249
250
251
252
253
254
  	.setattr = reiserfs_setattr,
  	.setxattr = reiserfs_setxattr,
  	.getxattr = reiserfs_getxattr,
  	.listxattr = reiserfs_listxattr,
  	.removexattr = reiserfs_removexattr,
  	.permission = reiserfs_permission,
4e34e719e   Christoph Hellwig   fs: take the ACL ...
255
  	.get_acl = reiserfs_get_acl,
47f70d08f   Christoph Hellwig   reiserfs: use gen...
256
  	.set_acl = reiserfs_set_acl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
  };