aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/file.c
diff options
context:
space:
mode:
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 /*