aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/file.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-27 23:52:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-27 23:52:25 -0400
commit173f8654746c138a08f51a8a0db7747763a896a2 (patch)
tree08e0fcd13c49e09fa8a15d7f4fb46535f13e454e /fs/ext4/file.c
parentcea8f46c36c3f82860b038aa23a46e16757666ba (diff)
parent03179fe92318e7934c180d96f12eff2cb36ef7b6 (diff)
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 updates from Ted Ts'o: "The usual collection of bug fixes and optimizations. Perhaps of greatest note is a speed up for parallel, non-allocating DIO writes, since we no longer take the i_mutex lock in that case. For bug fixes, we fix an incorrect overhead calculation which caused slightly incorrect results for df(1) and statfs(2). We also fixed bugs in the metadata checksum feature." * tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (23 commits) ext4: undo ext4_calc_metadata_amount if we fail to claim space ext4: don't let i_reserved_meta_blocks go negative ext4: fix hole punch failure when depth is greater than 0 ext4: remove unnecessary argument from __ext4_handle_dirty_metadata() ext4: weed out ext4_write_super ext4: remove unnecessary superblock dirtying ext4: convert last user of ext4_mark_super_dirty() to ext4_handle_dirty_super() ext4: remove useless marking of superblock dirty ext4: fix ext4 mismerge back in January ext4: remove dynamic array size in ext4_chksum() ext4: remove unused variable in ext4_update_super() ext4: make quota as first class supported feature ext4: don't take the i_mutex lock when doing DIO overwrites ext4: add a new nolock flag in ext4_map_blocks ext4: split ext4_file_write into buffered IO and direct IO ext4: remove an unused statement in ext4_mb_get_buddy_page_lock() ext4: fix out-of-date comments in extents.c ext4: use s_csum_seed instead of i_csum_seed for xattr block ext4: use proper csum calculation in ext4_rename ext4: fix overhead calculation used by ext4_statfs() ...
Diffstat (limited to 'fs/ext4/file.c')
-rw-r--r--fs/ext4/file.c121
1 files changed, 98 insertions, 23 deletions
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 782eecb57e43..3b0e3bdaabfc 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -90,11 +90,91 @@ ext4_unaligned_aio(struct inode *inode, const struct iovec *iov,
90} 90}
91 91
92static ssize_t 92static ssize_t
93ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
94 unsigned long nr_segs, loff_t pos)
95{
96 struct file *file = iocb->ki_filp;
97 struct inode *inode = file->f_mapping->host;
98 struct blk_plug plug;
99 int unaligned_aio = 0;
100 ssize_t ret;
101 int overwrite = 0;
102 size_t length = iov_length(iov, nr_segs);
103
104 if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
105 !is_sync_kiocb(iocb))
106 unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs, pos);
107
108 /* Unaligned direct AIO must be serialized; see comment above */
109 if (unaligned_aio) {
110 static unsigned long unaligned_warn_time;
111
112 /* Warn about this once per day */
113 if (printk_timed_ratelimit(&unaligned_warn_time, 60*60*24*HZ))
114 ext4_msg(inode->i_sb, KERN_WARNING,
115 "Unaligned AIO/DIO on inode %ld by %s; "
116 "performance will be poor.",
117 inode->i_ino, current->comm);
118 mutex_lock(ext4_aio_mutex(inode));
119 ext4_aiodio_wait(inode);
120 }
121
122 BUG_ON(iocb->ki_pos != pos);
123
124 mutex_lock(&inode->i_mutex);
125 blk_start_plug(&plug);
126
127 iocb->private = &overwrite;
128
129 /* check whether we do a DIO overwrite or not */
130 if (ext4_should_dioread_nolock(inode) && !unaligned_aio &&
131 !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) {
132 struct ext4_map_blocks map;
133 unsigned int blkbits = inode->i_blkbits;
134 int err, len;
135
136 map.m_lblk = pos >> blkbits;
137 map.m_len = (EXT4_BLOCK_ALIGN(pos + length, blkbits) >> blkbits)
138 - map.m_lblk;
139 len = map.m_len;
140
141 err = ext4_map_blocks(NULL, inode, &map, 0);
142 /*
143 * 'err==len' means that all of blocks has been preallocated no
144 * matter they are initialized or not. For excluding
145 * uninitialized extents, we need to check m_flags. There are
146 * two conditions that indicate for initialized extents.
147 * 1) If we hit extent cache, EXT4_MAP_MAPPED flag is returned;
148 * 2) If we do a real lookup, non-flags are returned.
149 * So we should check these two conditions.
150 */
151 if (err == len && (map.m_flags & EXT4_MAP_MAPPED))
152 overwrite = 1;
153 }
154
155 ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
156 mutex_unlock(&inode->i_mutex);
157
158 if (ret > 0 || ret == -EIOCBQUEUED) {
159 ssize_t err;
160
161 err = generic_write_sync(file, pos, ret);
162 if (err < 0 && ret > 0)
163 ret = err;
164 }
165 blk_finish_plug(&plug);
166
167 if (unaligned_aio)
168 mutex_unlock(ext4_aio_mutex(inode));
169
170 return ret;
171}
172
173static ssize_t
93ext4_file_write(struct kiocb *iocb, const struct iovec *iov, 174ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
94 unsigned long nr_segs, loff_t pos) 175 unsigned long nr_segs, loff_t pos)
95{ 176{
96 struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; 177 struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
97 int unaligned_aio = 0;
98 ssize_t ret; 178 ssize_t ret;
99 179
100 /* 180 /*
@@ -114,29 +194,12 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
114 nr_segs = iov_shorten((struct iovec *)iov, nr_segs, 194 nr_segs = iov_shorten((struct iovec *)iov, nr_segs,
115 sbi->s_bitmap_maxbytes - pos); 195 sbi->s_bitmap_maxbytes - pos);
116 } 196 }
117 } else if (unlikely((iocb->ki_filp->f_flags & O_DIRECT) &&
118 !is_sync_kiocb(iocb))) {
119 unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs, pos);
120 } 197 }
121 198
122 /* Unaligned direct AIO must be serialized; see comment above */ 199 if (unlikely(iocb->ki_filp->f_flags & O_DIRECT))
123 if (unaligned_aio) { 200 ret = ext4_file_dio_write(iocb, iov, nr_segs, pos);
124 static unsigned long unaligned_warn_time; 201 else
125 202 ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
126 /* Warn about this once per day */
127 if (printk_timed_ratelimit(&unaligned_warn_time, 60*60*24*HZ))
128 ext4_msg(inode->i_sb, KERN_WARNING,
129 "Unaligned AIO/DIO on inode %ld by %s; "
130 "performance will be poor.",
131 inode->i_ino, current->comm);
132 mutex_lock(ext4_aio_mutex(inode));
133 ext4_aiodio_wait(inode);
134 }
135
136 ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
137
138 if (unaligned_aio)
139 mutex_unlock(ext4_aio_mutex(inode));
140 203
141 return ret; 204 return ret;
142} 205}
@@ -181,9 +244,21 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
181 path.dentry = mnt->mnt_root; 244 path.dentry = mnt->mnt_root;
182 cp = d_path(&path, buf, sizeof(buf)); 245 cp = d_path(&path, buf, sizeof(buf));
183 if (!IS_ERR(cp)) { 246 if (!IS_ERR(cp)) {
247 handle_t *handle;
248 int err;
249
250 handle = ext4_journal_start_sb(sb, 1);
251 if (IS_ERR(handle))
252 return PTR_ERR(handle);
253 err = ext4_journal_get_write_access(handle, sbi->s_sbh);
254 if (err) {
255 ext4_journal_stop(handle);
256 return err;
257 }
184 strlcpy(sbi->s_es->s_last_mounted, cp, 258 strlcpy(sbi->s_es->s_last_mounted, cp,
185 sizeof(sbi->s_es->s_last_mounted)); 259 sizeof(sbi->s_es->s_last_mounted));
186 ext4_mark_super_dirty(sb); 260 ext4_handle_dirty_super(handle, sb);
261 ext4_journal_stop(handle);
187 } 262 }
188 } 263 }
189 /* 264 /*