Blame view

fs/ext4/file.c 7.27 KB
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
1
  /*
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
2
   *  linux/fs/ext4/file.c
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
3
4
5
6
7
8
9
10
11
12
13
14
   *
   * Copyright (C) 1992, 1993, 1994, 1995
   * Remy Card (card@masi.ibp.fr)
   * Laboratoire MASI - Institut Blaise Pascal
   * Universite Pierre et Marie Curie (Paris VI)
   *
   *  from
   *
   *  linux/fs/minix/file.c
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   *
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
15
   *  ext4 fs regular file handling primitives
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
16
17
18
19
20
21
22
   *
   *  64-bit file support on 64-bit platforms by Jakub Jelinek
   *	(jj@sunsite.ms.mff.cuni.cz)
   */
  
  #include <linux/time.h>
  #include <linux/fs.h>
dab291af8   Mingming Cao   [PATCH] jbd2: ena...
23
  #include <linux/jbd2.h>
bc0b0d6d6   Theodore Ts'o   ext4: update the ...
24
25
  #include <linux/mount.h>
  #include <linux/path.h>
871a29315   Christoph Hellwig   dquot: cleanup dq...
26
  #include <linux/quotaops.h>
3dcf54515   Christoph Hellwig   ext4: move header...
27
28
  #include "ext4.h"
  #include "ext4_jbd2.h"
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
29
30
31
32
33
  #include "xattr.h"
  #include "acl.h"
  
  /*
   * Called when an inode is released. Note that this is different
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
34
   * from ext4_file_open: open gets called at every open, but release
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
35
36
   * gets called only when /all/ the files are closed.
   */
af5bc92dd   Theodore Ts'o   ext4: Fix whitesp...
37
  static int ext4_release_file(struct inode *inode, struct file *filp)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
38
  {
19f5fb7ad   Theodore Ts'o   ext4: Use bitops ...
39
  	if (ext4_test_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE)) {
7d8f9f7d1   Theodore Ts'o   ext4: Automatical...
40
  		ext4_alloc_da_blocks(inode);
19f5fb7ad   Theodore Ts'o   ext4: Use bitops ...
41
  		ext4_clear_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE);
7d8f9f7d1   Theodore Ts'o   ext4: Automatical...
42
  	}
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
43
44
  	/* if we are the last writer on the inode, drop the block reservation */
  	if ((filp->f_mode & FMODE_WRITE) &&
d6014301b   Aneesh Kumar K.V   ext4: Fix discard...
45
46
  			(atomic_read(&inode->i_writecount) == 1) &&
  		        !EXT4_I(inode)->i_reserved_data_blocks)
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
47
  	{
0e855ac8b   Aneesh Kumar K.V   ext4: Convert tru...
48
  		down_write(&EXT4_I(inode)->i_data_sem);
c2ea3fde6   Theodore Ts'o   ext4: Remove old ...
49
  		ext4_discard_preallocations(inode);
0e855ac8b   Aneesh Kumar K.V   ext4: Convert tru...
50
  		up_write(&EXT4_I(inode)->i_data_sem);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
51
52
  	}
  	if (is_dx(inode) && filp->private_data)
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
53
  		ext4_htree_free_dir_info(filp->private_data);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
54
55
56
  
  	return 0;
  }
e9e3bcecf   Eric Sandeen   ext4: serialize u...
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  static void ext4_aiodio_wait(struct inode *inode)
  {
  	wait_queue_head_t *wq = ext4_ioend_wq(inode);
  
  	wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_aiodio_unwritten) == 0));
  }
  
  /*
   * This tests whether the IO in question is block-aligned or not.
   * Ext4 utilizes unwritten extents when hole-filling during direct IO, and they
   * are converted to written only after the IO is complete.  Until they are
   * mapped, these blocks appear as holes, so dio_zero_block() will assume that
   * it needs to zero out portions of the start and/or end block.  If 2 AIO
   * threads are at work on the same unwritten block, they must be synchronized
   * or one thread will zero the other's data, causing corruption.
   */
  static int
  ext4_unaligned_aio(struct inode *inode, const struct iovec *iov,
  		   unsigned long nr_segs, loff_t pos)
  {
  	struct super_block *sb = inode->i_sb;
  	int blockmask = sb->s_blocksize - 1;
  	size_t count = iov_length(iov, nr_segs);
  	loff_t final_size = pos + count;
  
  	if (pos >= inode->i_size)
  		return 0;
  
  	if ((pos & blockmask) || (final_size & blockmask))
  		return 1;
  
  	return 0;
  }
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
90
  static ssize_t
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
91
  ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
92
93
  		unsigned long nr_segs, loff_t pos)
  {
0d34ec62e   Jan Kara   ext4: Remove sync...
94
  	struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
e9e3bcecf   Eric Sandeen   ext4: serialize u...
95
96
  	int unaligned_aio = 0;
  	int ret;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
97

e2b465745   Eric Sandeen   ext4: store maxby...
98
99
100
101
  	/*
  	 * If we have encountered a bitmap-format file, the size limit
  	 * is smaller than s_maxbytes, which is for extent-mapped files.
  	 */
12e9b8920   Dmitry Monakhov   ext4: Use bitops ...
102
  	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
e2b465745   Eric Sandeen   ext4: store maxby...
103
104
  		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
  		size_t length = iov_length(iov, nr_segs);
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
105

d889dc838   Toshiyuki Okajima   ext4: fix EFBIG e...
106
107
  		if ((pos > sbi->s_bitmap_maxbytes ||
  		    (pos == sbi->s_bitmap_maxbytes && length > 0)))
e2b465745   Eric Sandeen   ext4: store maxby...
108
109
110
111
112
113
  			return -EFBIG;
  
  		if (pos + length > sbi->s_bitmap_maxbytes) {
  			nr_segs = iov_shorten((struct iovec *)iov, nr_segs,
  					      sbi->s_bitmap_maxbytes - pos);
  		}
e9e3bcecf   Eric Sandeen   ext4: serialize u...
114
115
116
  	} else if (unlikely((iocb->ki_filp->f_flags & O_DIRECT) &&
  		   !is_sync_kiocb(iocb))) {
  		unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs, pos);
e2b465745   Eric Sandeen   ext4: store maxby...
117
  	}
e9e3bcecf   Eric Sandeen   ext4: serialize u...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  	/* Unaligned direct AIO must be serialized; see comment above */
  	if (unaligned_aio) {
  		static unsigned long unaligned_warn_time;
  
  		/* Warn about this once per day */
  		if (printk_timed_ratelimit(&unaligned_warn_time, 60*60*24*HZ))
  			ext4_msg(inode->i_sb, KERN_WARNING,
  				 "Unaligned AIO/DIO on inode %ld by %s; "
  				 "performance will be poor.",
  				 inode->i_ino, current->comm);
  		mutex_lock(ext4_aio_mutex(inode));
  		ext4_aiodio_wait(inode);
  	}
  
  	ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
  
  	if (unaligned_aio)
  		mutex_unlock(ext4_aio_mutex(inode));
  
  	return ret;
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
138
  }
f0f37e2f7   Alexey Dobriyan   const: mark struc...
139
  static const struct vm_operations_struct ext4_file_vm_ops = {
2e9ee8503   Aneesh Kumar K.V   ext4: Use page_mk...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  	.fault		= filemap_fault,
  	.page_mkwrite   = ext4_page_mkwrite,
  };
  
  static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
  {
  	struct address_space *mapping = file->f_mapping;
  
  	if (!mapping->a_ops->readpage)
  		return -ENOEXEC;
  	file_accessed(file);
  	vma->vm_ops = &ext4_file_vm_ops;
  	vma->vm_flags |= VM_CAN_NONLINEAR;
  	return 0;
  }
bc0b0d6d6   Theodore Ts'o   ext4: update the ...
155
156
157
158
  static int ext4_file_open(struct inode * inode, struct file * filp)
  {
  	struct super_block *sb = inode->i_sb;
  	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
8aefcd557   Theodore Ts'o   ext4: dynamically...
159
  	struct ext4_inode_info *ei = EXT4_I(inode);
bc0b0d6d6   Theodore Ts'o   ext4: update the ...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  	struct vfsmount *mnt = filp->f_path.mnt;
  	struct path path;
  	char buf[64], *cp;
  
  	if (unlikely(!(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED) &&
  		     !(sb->s_flags & MS_RDONLY))) {
  		sbi->s_mount_flags |= EXT4_MF_MNTDIR_SAMPLED;
  		/*
  		 * Sample where the filesystem has been mounted and
  		 * store it in the superblock for sysadmin convenience
  		 * when trying to sort through large numbers of block
  		 * devices or filesystem images.
  		 */
  		memset(buf, 0, sizeof(buf));
3899167db   Al Viro   Get rid of mnt_mo...
174
175
  		path.mnt = mnt;
  		path.dentry = mnt->mnt_root;
bc0b0d6d6   Theodore Ts'o   ext4: update the ...
176
  		cp = d_path(&path, buf, sizeof(buf));
bc0b0d6d6   Theodore Ts'o   ext4: update the ...
177
  		if (!IS_ERR(cp)) {
cf8039036   Darrick J. Wong   ext4: prevent sta...
178
179
  			strlcpy(sbi->s_es->s_last_mounted, cp,
  				sizeof(sbi->s_es->s_last_mounted));
a0375156c   Theodore Ts'o   ext4: Clean up s_...
180
  			ext4_mark_super_dirty(sb);
bc0b0d6d6   Theodore Ts'o   ext4: update the ...
181
182
  		}
  	}
8aefcd557   Theodore Ts'o   ext4: dynamically...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
  	/*
  	 * Set up the jbd2_inode if we are opening the inode for
  	 * writing and the journal is present
  	 */
  	if (sbi->s_journal && !ei->jinode && (filp->f_mode & FMODE_WRITE)) {
  		struct jbd2_inode *jinode = jbd2_alloc_inode(GFP_KERNEL);
  
  		spin_lock(&inode->i_lock);
  		if (!ei->jinode) {
  			if (!jinode) {
  				spin_unlock(&inode->i_lock);
  				return -ENOMEM;
  			}
  			ei->jinode = jinode;
  			jbd2_journal_init_jbd_inode(ei->jinode, inode);
  			jinode = NULL;
  		}
  		spin_unlock(&inode->i_lock);
  		if (unlikely(jinode != NULL))
  			jbd2_free_inode(jinode);
  	}
907f4554e   Christoph Hellwig   dquot: move dquot...
204
  	return dquot_file_open(inode, filp);
bc0b0d6d6   Theodore Ts'o   ext4: update the ...
205
  }
e0d10bfa9   Toshiyuki Okajima   ext4: improve lls...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  /*
   * ext4_llseek() copied from generic_file_llseek() to handle both
   * block-mapped and extent-mapped maxbytes values. This should
   * otherwise be identical with generic_file_llseek().
   */
  loff_t ext4_llseek(struct file *file, loff_t offset, int origin)
  {
  	struct inode *inode = file->f_mapping->host;
  	loff_t maxbytes;
  
  	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
  		maxbytes = EXT4_SB(inode->i_sb)->s_bitmap_maxbytes;
  	else
  		maxbytes = inode->i_sb->s_maxbytes;
e0d10bfa9   Toshiyuki Okajima   ext4: improve lls...
220

4cce0e28b   Andi Kleen   ext4: replace cut...
221
  	return generic_file_llseek_size(file, offset, origin, maxbytes);
e0d10bfa9   Toshiyuki Okajima   ext4: improve lls...
222
  }
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
223
  const struct file_operations ext4_file_operations = {
e0d10bfa9   Toshiyuki Okajima   ext4: improve lls...
224
  	.llseek		= ext4_llseek,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
225
226
227
  	.read		= do_sync_read,
  	.write		= do_sync_write,
  	.aio_read	= generic_file_aio_read,
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
228
  	.aio_write	= ext4_file_write,
5cdd7b2d7   Andi Kleen   Convert ext4 to u...
229
  	.unlocked_ioctl = ext4_ioctl,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
230
  #ifdef CONFIG_COMPAT
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
231
  	.compat_ioctl	= ext4_compat_ioctl,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
232
  #endif
2e9ee8503   Aneesh Kumar K.V   ext4: Use page_mk...
233
  	.mmap		= ext4_file_mmap,
bc0b0d6d6   Theodore Ts'o   ext4: update the ...
234
  	.open		= ext4_file_open,
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
235
236
  	.release	= ext4_release_file,
  	.fsync		= ext4_sync_file,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
237
238
  	.splice_read	= generic_file_splice_read,
  	.splice_write	= generic_file_splice_write,
2fe17c107   Christoph Hellwig   fallocate should ...
239
  	.fallocate	= ext4_fallocate,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
240
  };
754661f14   Arjan van de Ven   [PATCH] mark stru...
241
  const struct inode_operations ext4_file_inode_operations = {
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
242
  	.setattr	= ext4_setattr,
3e3398a08   Mingming Cao   ext4: delayed all...
243
  	.getattr	= ext4_getattr,
03010a335   Theodore Ts'o   ext4: Rename ext4...
244
  #ifdef CONFIG_EXT4_FS_XATTR
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
245
246
  	.setxattr	= generic_setxattr,
  	.getxattr	= generic_getxattr,
617ba13b3   Mingming Cao   [PATCH] ext4: ren...
247
  	.listxattr	= ext4_listxattr,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
248
249
  	.removexattr	= generic_removexattr,
  #endif
4e34e719e   Christoph Hellwig   fs: take the ACL ...
250
  	.get_acl	= ext4_get_acl,
6873fa0de   Eric Sandeen   Hook ext4 to the ...
251
  	.fiemap		= ext4_fiemap,
ac27a0ec1   Dave Kleikamp   [PATCH] ext4: ini...
252
  };