diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2018-03-31 03:58:13 +0300 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2018-04-03 06:09:34 +0300 |
commit | dc7a10ddee0c56c6d891dd18de5c4ee9869545e0 (patch) | |
tree | fcb6036891e9abef8917ef162cb60d209acba084 /fs/f2fs/file.c | |
parent | 235831d7dd783ebd20e08ef4310dbdeeea46d87a (diff) | |
download | linux-dc7a10ddee0c56c6d891dd18de5c4ee9869545e0.tar.xz |
f2fs: truncate preallocated blocks in error case
If write is failed, we must deallocate the blocks that we couldn't write.
Cc: stable@vger.kernel.org
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/file.c')
-rw-r--r-- | fs/f2fs/file.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 8068b015ece5..6b94f19b3fa8 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2911,6 +2911,8 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ret = generic_write_checks(iocb, from); if (ret > 0) { + bool preallocated = false; + size_t target_size = 0; int err; if (iov_iter_fault_in_readable(from, iov_iter_count(from))) @@ -2927,6 +2929,9 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) } } else { + preallocated = true; + target_size = iocb->ki_pos + iov_iter_count(from); + err = f2fs_preallocate_blocks(iocb, from); if (err) { clear_inode_flag(inode, FI_NO_PREALLOC); @@ -2939,6 +2944,10 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) blk_finish_plug(&plug); clear_inode_flag(inode, FI_NO_PREALLOC); + /* if we couldn't write data, we should deallocate blocks. */ + if (preallocated && i_size_read(inode) < target_size) + f2fs_truncate(inode); + if (ret > 0) f2fs_update_iostat(F2FS_I_SB(inode), APP_WRITE_IO, ret); } |