Blame view

fs/reiserfs/file.c 10.5 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
5
6
7
  #include <linux/time.h>
  #include <linux/reiserfs_fs.h>
  #include <linux/reiserfs_acl.h>
  #include <linux/reiserfs_xattr.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  #include <asm/uaccess.h>
  #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>
  
  /*
  ** 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.
0222e6571   Jeff Mahoney   reiserfs: strip t...
22
  **
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
  ** 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.
0222e6571   Jeff Mahoney   reiserfs: strip t...
27
  **
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  ** We use reiserfs_truncate_file to pack the tail, since it already has
0222e6571   Jeff Mahoney   reiserfs: strip t...
29
  ** all the conditions coded.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  */
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
41
42
43
44
45
46
47
          if (atomic_add_unless(&REISERFS_I(inode)->openers, -1, 1))
  		return 0;
  
  	mutex_lock(&(REISERFS_I(inode)->tailpack));
  
          if (!atomic_dec_and_test(&REISERFS_I(inode)->openers)) {
  		mutex_unlock(&(REISERFS_I(inode)->tailpack));
  		return 0;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
48
  	/* fast out for when nothing needs to be done */
0e4f6a791   Al Viro   Fix reiserfs_file...
49
  	if ((!(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) ||
bd4c625c0   Linus Torvalds   reiserfs: run scr...
50
51
  	     !tail_has_to_be_packed(inode)) &&
  	    REISERFS_I(inode)->i_prealloc_count <= 0) {
0e4f6a791   Al Viro   Fix reiserfs_file...
52
  		mutex_unlock(&(REISERFS_I(inode)->tailpack));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
53
54
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55

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

bd4c625c0   Linus Torvalds   reiserfs: run scr...
101
102
103
104
105
106
107
  		/* 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 */
  		err = reiserfs_truncate_file(inode, 0);
  	}
        out:
bd4c625c0   Linus Torvalds   reiserfs: run scr...
108
  	reiserfs_write_unlock(inode->i_sb);
0e4f6a791   Al Viro   Fix reiserfs_file...
109
  	mutex_unlock(&(REISERFS_I(inode)->tailpack));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
110
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  }
0e4f6a791   Al Viro   Fix reiserfs_file...
112
  static int reiserfs_file_open(struct inode *inode, struct file *file)
de14569f9   Vladimir Saveliev   [PATCH] resierfs:...
113
  {
0e4f6a791   Al Viro   Fix reiserfs_file...
114
115
116
117
118
119
120
121
  	int err = dquot_file_open(inode, file);
          if (!atomic_inc_not_zero(&REISERFS_I(inode)->openers)) {
  		/* somebody might be tailpacking on final close; wait for it */
  		mutex_lock(&(REISERFS_I(inode)->tailpack));
  		atomic_inc(&REISERFS_I(inode)->openers);
  		mutex_unlock(&(REISERFS_I(inode)->tailpack));
  	}
  	return err;
de14569f9   Vladimir Saveliev   [PATCH] resierfs:...
122
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
123
124
  static void reiserfs_vfs_truncate_file(struct inode *inode)
  {
0e4f6a791   Al Viro   Fix reiserfs_file...
125
  	mutex_lock(&(REISERFS_I(inode)->tailpack));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
126
  	reiserfs_truncate_file(inode, 1);
0e4f6a791   Al Viro   Fix reiserfs_file...
127
  	mutex_unlock(&(REISERFS_I(inode)->tailpack));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
131
132
133
134
135
  }
  
  /* Sync a reiserfs file. */
  
  /*
   * FIXME: sync_mapping_buffers() never has anything to sync.  Can
   * be removed...
   */
02c24a821   Josef Bacik   fs: push i_mutex ...
136
137
  static int reiserfs_sync_file(struct file *filp, loff_t start, loff_t end,
  			      int datasync)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
138
  {
7ea808591   Christoph Hellwig   drop unused dentr...
139
  	struct inode *inode = filp->f_mapping->host;
ee93961be   Jeff Mahoney   reiserfs: rename ...
140
  	int err;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
141
  	int barrier_done;
02c24a821   Josef Bacik   fs: push i_mutex ...
142
143
144
145
146
  	err = filemap_write_and_wait_range(inode->i_mapping, start, end);
  	if (err)
  		return err;
  
  	mutex_lock(&inode->i_mutex);
995c762ea   Jeff Mahoney   reiserfs: rename ...
147
  	BUG_ON(!S_ISREG(inode->i_mode));
ee93961be   Jeff Mahoney   reiserfs: rename ...
148
  	err = sync_mapping_buffers(inode->i_mapping);
995c762ea   Jeff Mahoney   reiserfs: rename ...
149
150
151
152
  	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...
153
  		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
02c24a821   Josef Bacik   fs: push i_mutex ...
154
  	mutex_unlock(&inode->i_mutex);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
155
156
  	if (barrier_done < 0)
  		return barrier_done;
ee93961be   Jeff Mahoney   reiserfs: rename ...
157
  	return (err < 0) ? -EIO : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
  /* taken fs/buffer.c:__block_commit_write */
  int reiserfs_commit_page(struct inode *inode, struct page *page,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
161
  			 unsigned from, unsigned to)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
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
204
205
206
207
208
209
210
  	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);
  				journal_mark_dirty(&th, s, bh);
  			} else if (!buffer_dirty(bh)) {
  				mark_buffer_dirty(bh);
  				/* do data=ordered on any page past the end
  				 * 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
211
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  	if (logit) {
  		ret = journal_end(&th, s, bh_per_page + 1);
  	      drop_write_lock:
  		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
226
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
  /* Write @count bytes at position @ppos in a file indicated by @file
0222e6571   Jeff Mahoney   reiserfs: strip t...
228
     from the buffer @buf.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
  
     generic_file_write() is only appropriate for filesystems that are not seeking to optimize performance and want
     something simple that works.  It is not for serious use by general purpose filesystems, excepting the one that it was
     written for (ext2/3).  This is for several reasons:
  
     * It has no understanding of any filesystem specific optimizations.
  
     * It enters the filesystem repeatedly for each page that is written.
  
     * It depends on reiserfs_get_block() function which if implemented by reiserfs performs costly search_by_key
     * operation for each page it is supplied with. By contrast reiserfs_file_write() feeds as much as possible at a time
     * to reiserfs which allows for fewer tree traversals.
  
     * Each indirect pointer insertion takes a lot of cpu, because it involves memory moves inside of blocks.
  
     * Asking the block allocation code for blocks one at a time is slightly less efficient.
  
     All of these reasons for not using only generic file write were understood back when reiserfs was first miscoded to
     use it, but we were in a hurry to make code freeze, and so it couldn't be revised then.  This new code should make
     things right finally.
  
     Future Features: providing search_by_key with hints.
  
  */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
253
254
255
256
257
258
259
  static ssize_t reiserfs_file_write(struct file *file,	/* the file we are going to write into */
  				   const char __user * buf,	/*  pointer to user supplied data
  								   (in userspace) */
  				   size_t count,	/* amount of bytes to write */
  				   loff_t * ppos	/* pointer to position in file that we start writing at. Should be updated to
  							 * new current position before returning. */
  				   )
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
  {
1fc5adbd1   Josef Sipek   [PATCH] struct pa...
261
  	struct inode *inode = file->f_path.dentry->d_inode;	// Inode of the file that we are writing to.
bd4c625c0   Linus Torvalds   reiserfs: run scr...
262
263
  	/* To simplify coding at this time, we store
  	   locked pages in array for now */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
264
265
  	struct reiserfs_transaction_handle th;
  	th.t_trans_id = 0;
fa385bef2   Jeff Mahoney   [PATCH] reiserfs:...
266
267
268
269
270
271
272
273
274
275
  	/* If a filesystem is converted from 3.5 to 3.6, we'll have v3.5 items
  	* lying around (most of the disk, in fact). Despite the filesystem
  	* now being a v3.6 format, the old items still can't support large
  	* file sizes. Catch this case here, as the rest of the VFS layer is
  	* oblivious to the different limitations between old and new items.
  	* reiserfs_setattr catches this for truncates. This chunk is lifted
  	* from generic_write_checks. */
  	if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 &&
  	    *ppos + count > MAX_NON_LFS) {
  		if (*ppos >= MAX_NON_LFS) {
fa385bef2   Jeff Mahoney   [PATCH] reiserfs:...
276
277
278
279
280
  			return -EFBIG;
  		}
  		if (count > MAX_NON_LFS - (unsigned long)*ppos)
  			count = MAX_NON_LFS - (unsigned long)*ppos;
  	}
797b4cffd   Vladimir Saveliev   reiserfs: use gen...
281
  	return do_sync_write(file, buf, count, ppos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
  }
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
283
  const struct file_operations reiserfs_file_operations = {
027445c37   Badari Pulavarty   [PATCH] Vectorize...
284
  	.read = do_sync_read,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
285
  	.write = reiserfs_file_write,
205cb37b8   Frederic Weisbecker   kill-the-bkl/reis...
286
  	.unlocked_ioctl = reiserfs_ioctl,
52b499c43   David Howells   [PATCH] BLOCK: Mo...
287
288
289
  #ifdef CONFIG_COMPAT
  	.compat_ioctl = reiserfs_compat_ioctl,
  #endif
0e4f6a791   Al Viro   Fix reiserfs_file...
290
291
  	.mmap = generic_file_mmap,
  	.open = reiserfs_file_open,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
292
293
  	.release = reiserfs_file_release,
  	.fsync = reiserfs_sync_file,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
294
  	.aio_read = generic_file_aio_read,
9637f28f8   Alexey Dobriyan   [PATCH] reiserfs:...
295
  	.aio_write = generic_file_aio_write,
5274f052e   Jens Axboe   [PATCH] Introduce...
296
297
  	.splice_read = generic_file_splice_read,
  	.splice_write = generic_file_splice_write,
91efc167d   Christoph Hellwig   [PATCH] reiserfs:...
298
  	.llseek = generic_file_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
  };
c5ef1c42c   Arjan van de Ven   [PATCH] mark stru...
300
  const struct inode_operations reiserfs_file_inode_operations = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
301
302
303
304
305
306
307
  	.truncate = reiserfs_vfs_truncate_file,
  	.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 ...
308
  	.get_acl = reiserfs_get_acl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
  };