f2fs: fix to align to section for fallocate() on pinned file
[ Upstream commit e1175f02291141bbd924fc578299305fcde35855 ] Now, fallocate() on a pinned file only allocates blocks which aligns to segment rather than section, so GC may try to migrate pinned file's block, and after several times of failure, pinned file's block could be migrated to other place, however user won't be aware of such condition, and then old obsolete block address may be readed/written incorrectly. To avoid such condition, let's try to allocate pinned file's blocks with section alignment. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
6301462031
commit
74d2b0e74c
@@ -1643,27 +1643,26 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
|
||||
return 0;
|
||||
|
||||
if (f2fs_is_pinned_file(inode)) {
|
||||
block_t len = (map.m_len >> sbi->log_blocks_per_seg) <<
|
||||
sbi->log_blocks_per_seg;
|
||||
block_t sec_blks = BLKS_PER_SEC(sbi);
|
||||
block_t sec_len = roundup(map.m_len, sec_blks);
|
||||
block_t done = 0;
|
||||
|
||||
if (map.m_len % sbi->blocks_per_seg)
|
||||
len += sbi->blocks_per_seg;
|
||||
|
||||
map.m_len = sbi->blocks_per_seg;
|
||||
map.m_len = sec_blks;
|
||||
next_alloc:
|
||||
if (has_not_enough_free_secs(sbi, 0,
|
||||
GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi)))) {
|
||||
down_write(&sbi->gc_lock);
|
||||
err = f2fs_gc(sbi, true, false, false, NULL_SEGNO);
|
||||
if (err && err != -ENODATA && err != -EAGAIN)
|
||||
if (err && err != -ENODATA && err != -EAGAIN) {
|
||||
map.m_len = done;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
down_write(&sbi->pin_sem);
|
||||
|
||||
f2fs_lock_op(sbi);
|
||||
f2fs_allocate_new_segment(sbi, CURSEG_COLD_DATA_PINNED);
|
||||
f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED);
|
||||
f2fs_unlock_op(sbi);
|
||||
|
||||
map.m_seg_type = CURSEG_COLD_DATA_PINNED;
|
||||
@@ -1672,9 +1671,9 @@ next_alloc:
|
||||
up_write(&sbi->pin_sem);
|
||||
|
||||
done += map.m_len;
|
||||
len -= map.m_len;
|
||||
sec_len -= map.m_len;
|
||||
map.m_lblk += map.m_len;
|
||||
if (!err && len)
|
||||
if (!err && sec_len)
|
||||
goto next_alloc;
|
||||
|
||||
map.m_len = done;
|
||||
|
Reference in New Issue
Block a user