aboutsummaryrefslogtreecommitdiff
path: root/fs/f2fs/data.c
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2016-11-11 16:46:40 -0800
committerMister Oyster <oysterized@gmail.com>2017-04-13 12:34:28 +0200
commit8cb73da38fa3eac200cb004cf4b214ffe0855208 (patch)
treeefc5372a4c4ca2a3bce05fdc9ea521127fe9353a /fs/f2fs/data.c
parentd78ce8ef2e85e4f1e5006377100ae99a2e45bbae (diff)
f2fs: fix redundant block allocation
In direct_IO path of f2fs_file_write_iter(), 1. f2fs_preallocate_blocks(F2FS_GET_BLOCK_PRE_DIO) -> allocate LBA X 2. f2fs_direct_IO() -> return 0; Then, f2fs_write_data_page() will allocate another LBA X+1. This makes EIO triggered by HM-SMR. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> Conflicts: fs/f2fs/data.c
Diffstat (limited to 'fs/f2fs/data.c')
-rw-r--r--fs/f2fs/data.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index aa3671c78..e325593fc 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -653,6 +653,13 @@ alloc:
return 0;
}
+static inline bool __force_buffered_io(struct inode *inode, int rw)
+{
+ return ((f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) ||
+ (rw == WRITE && test_opt(F2FS_I_SB(inode), LFS)) ||
+ F2FS_I_SB(inode)->s_ndevs);
+}
+
int f2fs_preallocate_blocks(struct inode *inode, loff_t pos,
size_t count, bool dio)
{
@@ -672,7 +679,10 @@ int f2fs_preallocate_blocks(struct inode *inode, loff_t pos,
err = f2fs_convert_inline_inode(inode);
if (err)
return err;
- return f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_DIO);
+ return f2fs_map_blocks(inode, &map, 1,
+ __force_buffered_io(inode, WRITE) ?
+ F2FS_GET_BLOCK_PRE_AIO :
+ F2FS_GET_BLOCK_PRE_DIO);
}
if (pos + count > MAX_INLINE_DATA) {
err = f2fs_convert_inline_inode(inode);
@@ -1787,11 +1797,7 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb,
if (err)
return err;
- if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
- return 0;
- if (rw == WRITE && test_opt(F2FS_I_SB(inode), LFS))
- return 0;
- if (F2FS_I_SB(inode)->s_ndevs)
+ if (__force_buffered_io(inode, rw))
return 0;
trace_f2fs_direct_IO_enter(inode, offset, count, rw);