On Dec 03, 2019 / 09:33, Jaegeuk Kim wrote: > Thank you for checking the patch. > I found some regressions in xfstests, so want to follow the Damien's one > like below. > > Thanks, > > === > From 9df6f09e3a09ed804aba4b56ff7cd9524c002e69 Mon Sep 17 00:00:00 2001 > From: Jaegeuk Kim <jaegeuk@xxxxxxxxxx> > Date: Tue, 26 Nov 2019 15:01:42 -0800 > Subject: [PATCH] f2fs: preallocate DIO blocks when forcing buffered_io > > The previous preallocation and DIO decision like below. > > allow_outplace_dio !allow_outplace_dio > f2fs_force_buffered_io (*) No_Prealloc / Buffered_IO Prealloc / Buffered_IO > !f2fs_force_buffered_io No_Prealloc / DIO Prealloc / DIO > > But, Javier reported Case (*) where zoned device bypassed preallocation but > fell back to buffered writes in f2fs_direct_IO(), resulting in stale data > being read. > > In order to fix the issue, actually we need to preallocate blocks whenever > we fall back to buffered IO like this. No change is made in the other cases. > > allow_outplace_dio !allow_outplace_dio > f2fs_force_buffered_io (*) Prealloc / Buffered_IO Prealloc / Buffered_IO > !f2fs_force_buffered_io No_Prealloc / DIO Prealloc / DIO > > Reported-and-tested-by: Javier Gonzalez <javier@xxxxxxxxxxx> > Signed-off-by: Damien Le Moal <damien.lemoal@xxxxxxx> > Tested-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@xxxxxxx> > Signed-off-by: Jaegeuk Kim <jaegeuk@xxxxxxxxxx> Using SMR disks, I reconfirmed that the reported problem goes away with this modified patch also. Thanks. > --- > fs/f2fs/data.c | 13 ------------- > fs/f2fs/file.c | 43 +++++++++++++++++++++++++++++++++---------- > 2 files changed, 33 insertions(+), 23 deletions(-) > > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c > index a034cd0ce021..fc40a72f7827 100644 > --- a/fs/f2fs/data.c > +++ b/fs/f2fs/data.c > @@ -1180,19 +1180,6 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from) > int err = 0; > bool direct_io = iocb->ki_flags & IOCB_DIRECT; > > - /* convert inline data for Direct I/O*/ > - if (direct_io) { > - err = f2fs_convert_inline_inode(inode); > - if (err) > - return err; > - } > - > - if (direct_io && allow_outplace_dio(inode, iocb, from)) > - return 0; > - > - if (is_inode_flag_set(inode, FI_NO_PREALLOC)) > - return 0; > - > map.m_lblk = F2FS_BLK_ALIGN(iocb->ki_pos); > map.m_len = F2FS_BYTES_TO_BLK(iocb->ki_pos + iov_iter_count(from)); > if (map.m_len > map.m_lblk) > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c > index c0560d62dbee..0e1b12a4a4d6 100644 > --- a/fs/f2fs/file.c > +++ b/fs/f2fs/file.c > @@ -3386,18 +3386,41 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) > ret = -EAGAIN; > goto out; > } > - } else { > - preallocated = true; > - target_size = iocb->ki_pos + iov_iter_count(from); > + goto write; > + } > > - err = f2fs_preallocate_blocks(iocb, from); > - if (err) { > - clear_inode_flag(inode, FI_NO_PREALLOC); > - inode_unlock(inode); > - ret = err; > - goto out; > - } > + if (is_inode_flag_set(inode, FI_NO_PREALLOC)) > + goto write; > + > + if (iocb->ki_flags & IOCB_DIRECT) { > + /* > + * Convert inline data for Direct I/O before entering > + * f2fs_direct_IO(). > + */ > + err = f2fs_convert_inline_inode(inode); > + if (err) > + goto out_err; > + /* > + * If force_buffere_io() is true, we have to allocate > + * blocks all the time, since f2fs_direct_IO will fall > + * back to buffered IO. > + */ > + if (!f2fs_force_buffered_io(inode, iocb, from) && > + allow_outplace_dio(inode, iocb, from)) > + goto write; > + } > + preallocated = true; > + target_size = iocb->ki_pos + iov_iter_count(from); > + > + err = f2fs_preallocate_blocks(iocb, from); > + if (err) { > +out_err: > + clear_inode_flag(inode, FI_NO_PREALLOC); > + inode_unlock(inode); > + ret = err; > + goto out; > } > +write: > ret = __generic_file_write_iter(iocb, from); > clear_inode_flag(inode, FI_NO_PREALLOC); > > -- > 2.19.0.605.g01d371f741-goog > > -- Best Regards, Shin'ichiro Kawasaki