Skip to content

Commit 3d697a4

Browse files
ebiggersJaegeuk Kim
authored andcommitted
f2fs: rework write preallocations
f2fs_write_begin() assumes that all blocks were preallocated by default unless FI_NO_PREALLOC is explicitly set. This invites data corruption, as there are cases in which not all blocks are preallocated. Commit 47501f8 ("f2fs: preallocate DIO blocks when forcing buffered_io") fixed one case, but there are others remaining. Fix up this logic by replacing this flag with FI_PREALLOCATED_ALL, which only gets set if all blocks for the current write were preallocated. Also clean up f2fs_preallocate_blocks(), move it to file.c, and make it handle some of the logic that was previously in write_iter() directly. Signed-off-by: Eric Biggers <[email protected]> Reviewed-by: Chao Yu <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent 3271d7e commit 3d697a4

File tree

3 files changed

+88
-101
lines changed

3 files changed

+88
-101
lines changed

fs/f2fs/data.c

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,53 +1384,6 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
13841384
return 0;
13851385
}
13861386

1387-
int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from)
1388-
{
1389-
struct inode *inode = file_inode(iocb->ki_filp);
1390-
struct f2fs_map_blocks map;
1391-
int flag;
1392-
int err = 0;
1393-
bool direct_io = iocb->ki_flags & IOCB_DIRECT;
1394-
1395-
map.m_lblk = F2FS_BLK_ALIGN(iocb->ki_pos);
1396-
map.m_len = F2FS_BYTES_TO_BLK(iocb->ki_pos + iov_iter_count(from));
1397-
if (map.m_len > map.m_lblk)
1398-
map.m_len -= map.m_lblk;
1399-
else
1400-
map.m_len = 0;
1401-
1402-
map.m_next_pgofs = NULL;
1403-
map.m_next_extent = NULL;
1404-
map.m_seg_type = NO_CHECK_TYPE;
1405-
map.m_may_create = true;
1406-
1407-
if (direct_io) {
1408-
map.m_seg_type = f2fs_rw_hint_to_seg_type(iocb->ki_hint);
1409-
flag = f2fs_force_buffered_io(inode, iocb, from) ?
1410-
F2FS_GET_BLOCK_PRE_AIO :
1411-
F2FS_GET_BLOCK_PRE_DIO;
1412-
goto map_blocks;
1413-
}
1414-
if (iocb->ki_pos + iov_iter_count(from) > MAX_INLINE_DATA(inode)) {
1415-
err = f2fs_convert_inline_inode(inode);
1416-
if (err)
1417-
return err;
1418-
}
1419-
if (f2fs_has_inline_data(inode))
1420-
return err;
1421-
1422-
flag = F2FS_GET_BLOCK_PRE_AIO;
1423-
1424-
map_blocks:
1425-
err = f2fs_map_blocks(inode, &map, 1, flag);
1426-
if (map.m_len > 0 && err == -ENOSPC) {
1427-
if (!direct_io)
1428-
set_inode_flag(inode, FI_NO_PREALLOC);
1429-
err = 0;
1430-
}
1431-
return err;
1432-
}
1433-
14341387
void f2fs_do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock)
14351388
{
14361389
if (flag == F2FS_GET_BLOCK_PRE_AIO) {
@@ -3340,12 +3293,10 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
33403293
int flag;
33413294

33423295
/*
3343-
* we already allocated all the blocks, so we don't need to get
3344-
* the block addresses when there is no need to fill the page.
3296+
* If a whole page is being written and we already preallocated all the
3297+
* blocks, then there is no need to get a block address now.
33453298
*/
3346-
if (!f2fs_has_inline_data(inode) && len == PAGE_SIZE &&
3347-
!is_inode_flag_set(inode, FI_NO_PREALLOC) &&
3348-
!f2fs_verity_in_progress(inode))
3299+
if (len == PAGE_SIZE && is_inode_flag_set(inode, FI_PREALLOCATED_ALL))
33493300
return 0;
33503301

33513302
/* f2fs_lock_op avoids race between write CP and convert_inline_page */

fs/f2fs/f2fs.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ enum {
715715
FI_INLINE_DOTS, /* indicate inline dot dentries */
716716
FI_DO_DEFRAG, /* indicate defragment is running */
717717
FI_DIRTY_FILE, /* indicate regular/symlink has dirty pages */
718-
FI_NO_PREALLOC, /* indicate skipped preallocated blocks */
718+
FI_PREALLOCATED_ALL, /* all blocks for write were preallocated */
719719
FI_HOT_DATA, /* indicate file is hot */
720720
FI_EXTRA_ATTR, /* indicate file has extra attribute */
721721
FI_PROJ_INHERIT, /* indicate file inherits projectid */
@@ -3615,7 +3615,6 @@ void f2fs_update_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr);
36153615
int f2fs_reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count);
36163616
int f2fs_reserve_new_block(struct dnode_of_data *dn);
36173617
int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index);
3618-
int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from);
36193618
int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index);
36203619
struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
36213620
int op_flags, bool for_write);

fs/f2fs/file.c

Lines changed: 84 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4235,10 +4235,77 @@ static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
42354235
return ret;
42364236
}
42374237

4238+
/*
4239+
* Preallocate blocks for a write request, if it is possible and helpful to do
4240+
* so. Returns a positive number if blocks may have been preallocated, 0 if no
4241+
* blocks were preallocated, or a negative errno value if something went
4242+
* seriously wrong. Also sets FI_PREALLOCATED_ALL on the inode if *all* the
4243+
* requested blocks (not just some of them) have been allocated.
4244+
*/
4245+
static int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *iter)
4246+
{
4247+
struct inode *inode = file_inode(iocb->ki_filp);
4248+
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
4249+
const loff_t pos = iocb->ki_pos;
4250+
const size_t count = iov_iter_count(iter);
4251+
struct f2fs_map_blocks map = {};
4252+
bool dio = (iocb->ki_flags & IOCB_DIRECT) &&
4253+
!f2fs_force_buffered_io(inode, iocb, iter);
4254+
int flag;
4255+
int ret;
4256+
4257+
/* If it will be an out-of-place direct write, don't bother. */
4258+
if (dio && f2fs_lfs_mode(sbi))
4259+
return 0;
4260+
4261+
/* No-wait I/O can't allocate blocks. */
4262+
if (iocb->ki_flags & IOCB_NOWAIT)
4263+
return 0;
4264+
4265+
/* If it will be a short write, don't bother. */
4266+
if (fault_in_iov_iter_readable(iter, count))
4267+
return 0;
4268+
4269+
if (f2fs_has_inline_data(inode)) {
4270+
/* If the data will fit inline, don't bother. */
4271+
if (pos + count <= MAX_INLINE_DATA(inode))
4272+
return 0;
4273+
ret = f2fs_convert_inline_inode(inode);
4274+
if (ret)
4275+
return ret;
4276+
}
4277+
4278+
/* Do not preallocate blocks that will be written partially in 4KB. */
4279+
map.m_lblk = F2FS_BLK_ALIGN(pos);
4280+
map.m_len = F2FS_BYTES_TO_BLK(pos + count);
4281+
if (map.m_len > map.m_lblk)
4282+
map.m_len -= map.m_lblk;
4283+
else
4284+
map.m_len = 0;
4285+
map.m_may_create = true;
4286+
if (dio) {
4287+
map.m_seg_type = f2fs_rw_hint_to_seg_type(inode->i_write_hint);
4288+
flag = F2FS_GET_BLOCK_PRE_DIO;
4289+
} else {
4290+
map.m_seg_type = NO_CHECK_TYPE;
4291+
flag = F2FS_GET_BLOCK_PRE_AIO;
4292+
}
4293+
4294+
ret = f2fs_map_blocks(inode, &map, 1, flag);
4295+
/* -ENOSPC is only a fatal error if no blocks could be allocated. */
4296+
if (ret < 0 && !(ret == -ENOSPC && map.m_len > 0))
4297+
return ret;
4298+
if (ret == 0)
4299+
set_inode_flag(inode, FI_PREALLOCATED_ALL);
4300+
return map.m_len;
4301+
}
4302+
42384303
static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
42394304
{
42404305
struct file *file = iocb->ki_filp;
42414306
struct inode *inode = file_inode(file);
4307+
loff_t target_size;
4308+
int preallocated;
42424309
ssize_t ret;
42434310

42444311
if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) {
@@ -4262,84 +4329,54 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
42624329

42634330
if (unlikely(IS_IMMUTABLE(inode))) {
42644331
ret = -EPERM;
4265-
goto unlock;
4332+
goto out_unlock;
42664333
}
42674334

42684335
if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) {
42694336
ret = -EPERM;
4270-
goto unlock;
4337+
goto out_unlock;
42714338
}
42724339

42734340
ret = generic_write_checks(iocb, from);
42744341
if (ret > 0) {
4275-
bool preallocated = false;
4276-
size_t target_size = 0;
4277-
int err;
4278-
4279-
if (fault_in_iov_iter_readable(from, iov_iter_count(from)))
4280-
set_inode_flag(inode, FI_NO_PREALLOC);
4281-
4282-
if ((iocb->ki_flags & IOCB_NOWAIT)) {
4342+
if (iocb->ki_flags & IOCB_NOWAIT) {
42834343
if (!f2fs_overwrite_io(inode, iocb->ki_pos,
42844344
iov_iter_count(from)) ||
42854345
f2fs_has_inline_data(inode) ||
42864346
f2fs_force_buffered_io(inode, iocb, from)) {
4287-
clear_inode_flag(inode, FI_NO_PREALLOC);
4288-
inode_unlock(inode);
42894347
ret = -EAGAIN;
4290-
goto out;
4348+
goto out_unlock;
42914349
}
4292-
goto write;
42934350
}
4294-
4295-
if (is_inode_flag_set(inode, FI_NO_PREALLOC))
4296-
goto write;
4297-
42984351
if (iocb->ki_flags & IOCB_DIRECT) {
4299-
/*
4300-
* Convert inline data for Direct I/O before entering
4301-
* f2fs_direct_IO().
4302-
*/
4303-
err = f2fs_convert_inline_inode(inode);
4304-
if (err)
4305-
goto out_err;
4306-
/*
4307-
* If force_buffere_io() is true, we have to allocate
4308-
* blocks all the time, since f2fs_direct_IO will fall
4309-
* back to buffered IO.
4310-
*/
4311-
if (!f2fs_force_buffered_io(inode, iocb, from) &&
4312-
f2fs_lfs_mode(F2FS_I_SB(inode)))
4313-
goto write;
4352+
ret = f2fs_convert_inline_inode(inode);
4353+
if (ret)
4354+
goto out_unlock;
43144355
}
4315-
preallocated = true;
4356+
/* Possibly preallocate the blocks for the write. */
43164357
target_size = iocb->ki_pos + iov_iter_count(from);
4317-
4318-
err = f2fs_preallocate_blocks(iocb, from);
4319-
if (err) {
4320-
out_err:
4321-
clear_inode_flag(inode, FI_NO_PREALLOC);
4322-
inode_unlock(inode);
4323-
ret = err;
4324-
goto out;
4358+
preallocated = f2fs_preallocate_blocks(iocb, from);
4359+
if (preallocated < 0) {
4360+
ret = preallocated;
4361+
goto out_unlock;
43254362
}
4326-
write:
4363+
43274364
ret = __generic_file_write_iter(iocb, from);
4328-
clear_inode_flag(inode, FI_NO_PREALLOC);
43294365

4330-
/* if we couldn't write data, we should deallocate blocks. */
4331-
if (preallocated && i_size_read(inode) < target_size) {
4366+
/* Don't leave any preallocated blocks around past i_size. */
4367+
if (preallocated > 0 && i_size_read(inode) < target_size) {
43324368
down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
43334369
filemap_invalidate_lock(inode->i_mapping);
43344370
f2fs_truncate(inode);
43354371
filemap_invalidate_unlock(inode->i_mapping);
43364372
up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
43374373
}
4374+
clear_inode_flag(inode, FI_PREALLOCATED_ALL);
43384375

43394376
if (ret > 0)
43404377
f2fs_update_iostat(F2FS_I_SB(inode), APP_WRITE_IO, ret);
43414378
}
4342-
unlock:
4379+
out_unlock:
43434380
inode_unlock(inode);
43444381
out:
43454382
trace_f2fs_file_write_iter(inode, iocb->ki_pos,

0 commit comments

Comments
 (0)