Skip to content

Commit 5fa6484

Browse files
biger410Brian Maly
authored andcommitted
ext4: refactor ext4_file_write_iter
commit aa9714d("Start with shared i_rwsem in case of DIO instead of exclusive") allowed shared inode lock using in directio overwite case, that can improve a lot performance for mixed read/write directio workload like database. This feature was done from upstream when ext4 directio was already switched to iomap infrastructure, but that had not been supported until uek7, one way to do it is to backport the iomap feature to older uek, but that introduced a lot of patches and has high risk especially the change is in io critical path, it could introuduce corruption issue, so we decides to manually refactor the directio path to resolve the dependency above patch requires. For that, we need refactoring ext4_file_write_iter and split out two helpers, one is ext4_buffered_write_iter, and another is ext4_dio_write_iter. For the case that directio fallen into buffer io, dio helper will invoke buffer io helper. That way we can release inode lock dio helper taken before fallen into buffer io helper. No function changes. Orabug: 34405736 Signed-off-by: Junxiao Bi <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Brian Maly <[email protected]>
1 parent cb28a49 commit 5fa6484

File tree

1 file changed

+51
-13
lines changed

1 file changed

+51
-13
lines changed

fs/ext4/file.c

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -216,22 +216,41 @@ ext4_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
216216
}
217217
#endif
218218

219-
static ssize_t
220-
ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
219+
static ssize_t ext4_buffered_write_iter(struct kiocb *iocb,
220+
struct iov_iter *from)
221221
{
222222
struct inode *inode = file_inode(iocb->ki_filp);
223-
int o_direct = iocb->ki_flags & IOCB_DIRECT;
224-
int unaligned_aio = 0;
225-
int overwrite = 0;
226223
ssize_t ret;
227224

228-
if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
229-
return -EIO;
225+
if (!inode_trylock(inode)) {
226+
if (iocb->ki_flags & IOCB_NOWAIT)
227+
return -EAGAIN;
228+
inode_lock(inode);
229+
}
230230

231-
#ifdef CONFIG_FS_DAX
232-
if (IS_DAX(inode))
233-
return ext4_dax_write_iter(iocb, from);
234-
#endif
231+
ret = ext4_write_checks(iocb, from);
232+
if (ret <= 0)
233+
goto out;
234+
235+
ret = __generic_file_write_iter(iocb, from);
236+
inode_unlock(inode);
237+
238+
if (ret > 0)
239+
ret = generic_write_sync(iocb, ret);
240+
241+
return ret;
242+
243+
out:
244+
inode_unlock(inode);
245+
return ret;
246+
}
247+
248+
static ssize_t ext4_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
249+
{
250+
struct inode *inode = file_inode(iocb->ki_filp);
251+
int unaligned_aio = 0;
252+
int overwrite = 0;
253+
ssize_t ret;
235254

236255
if (!inode_trylock(inode)) {
237256
if (iocb->ki_flags & IOCB_NOWAIT)
@@ -248,7 +267,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
248267
* of partial blocks of two competing unaligned AIOs can result in data
249268
* corruption.
250269
*/
251-
if (o_direct && ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
270+
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
252271
!is_sync_kiocb(iocb) &&
253272
ext4_unaligned_aio(inode, from, iocb->ki_pos)) {
254273
unaligned_aio = 1;
@@ -257,7 +276,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
257276

258277
iocb->private = &overwrite;
259278
/* Check whether we do a DIO overwrite or not */
260-
if (o_direct && !unaligned_aio) {
279+
if (!unaligned_aio) {
261280
if (ext4_overwrite_io(inode, iocb->ki_pos, iov_iter_count(from))) {
262281
if (ext4_should_dioread_nolock(inode))
263282
overwrite = 1;
@@ -287,6 +306,25 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
287306
return ret;
288307
}
289308

309+
static ssize_t
310+
ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
311+
{
312+
struct inode *inode = file_inode(iocb->ki_filp);
313+
314+
if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
315+
return -EIO;
316+
317+
#ifdef CONFIG_FS_DAX
318+
if (IS_DAX(inode))
319+
return ext4_dax_write_iter(iocb, from);
320+
#endif
321+
322+
if (iocb->ki_flags & IOCB_DIRECT)
323+
return ext4_dio_write_iter(iocb, from);
324+
325+
return ext4_buffered_write_iter(iocb, from);
326+
}
327+
290328
#ifdef CONFIG_FS_DAX
291329
static vm_fault_t ext4_dax_huge_fault(struct vm_fault *vmf,
292330
enum page_entry_size pe_size)

0 commit comments

Comments
 (0)