Skip to content

Commit f0a7adf

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: don't break allocation when crossing contiguous sections
Commit 0638a31 ("f2fs: avoid unused block when dio write in LFS mode") has fixed unused block issue for dio write in lfs mode. However, f2fs_map_blocks() may break and return smaller extent when last allocated block locates in the end of section, even allocator can allocate contiguous blocks across sections. Actually, for the case that allocator returns a block address which is not contiguous w/ current extent, we can record the block address in iomap->private, in the next round, skip reallocating for the last allocated block, then we can fix unused block issue, meanwhile, also, we can allocates contiguous physical blocks as much as possible for dio write in lfs mode. Testcase: - mkfs.f2fs -f /dev/vdb - mount -o mode=lfs /dev/vdb /mnt/f2fs - dd if=/dev/zero of=/mnt/f2fs/file bs=1M count=3; sync; - dd if=/dev/zero of=/mnt/f2fs/dio bs=2M count=1 oflag=direct; - umount /mnt/f2fs Before: f2fs_map_blocks: dev = (253,16), ino = 4, file offset = 0, start blkaddr = 0x0, len = 0x100, flags = 1, seg_type = 8, may_create = 1, multidevice = 0, flag = 5, err = 0 f2fs_map_blocks: dev = (253,16), ino = 4, file offset = 256, start blkaddr = 0x0, len = 0x100, flags = 1, seg_type = 8, may_create = 1, multidevice = 0, flag = 5, err = 0 f2fs_map_blocks: dev = (253,16), ino = 4, file offset = 512, start blkaddr = 0x0, len = 0x100, flags = 1, seg_type = 8, may_create = 1, multidevice = 0, flag = 5, err = 0 f2fs_map_blocks: dev = (253,16), ino = 5, file offset = 0, start blkaddr = 0x4700, len = 0x100, flags = 3, seg_type = 1, may_create = 1, multidevice = 0, flag = 3, err = 0 f2fs_map_blocks: dev = (253,16), ino = 5, file offset = 256, start blkaddr = 0x4800, len = 0x100, flags = 3, seg_type = 1, may_create = 1, multidevice = 0, flag = 3, err = 0 After: f2fs_map_blocks: dev = (253,16), ino = 4, file offset = 0, start blkaddr = 0x0, len = 0x100, flags = 1, seg_type = 8, may_create = 1, multidevice = 0, flag = 5, err = 0 f2fs_map_blocks: dev = (253,16), ino = 4, file offset = 256, start blkaddr = 0x0, len = 0x100, flags = 1, seg_type = 8, may_create = 1, multidevice = 0, flag = 5, err = 0 f2fs_map_blocks: dev = (253,16), ino = 4, file offset = 512, start blkaddr = 0x0, len = 0x100, flags = 1, seg_type = 8, may_create = 1, multidevice = 0, flag = 5, err = 0 f2fs_map_blocks: dev = (253,16), ino = 5, file offset = 0, start blkaddr = 0x4700, len = 0x200, flags = 3, seg_type = 1, may_create = 1, multidevice = 0, flag = 3, err = 0 Cc: Daejun Park <[email protected]> Signed-off-by: Chao Yu <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent 95d7c50 commit f0a7adf

File tree

2 files changed

+19
-10
lines changed

2 files changed

+19
-10
lines changed

fs/f2fs/data.c

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,10 +1550,14 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag)
15501550
unsigned int start_pgofs;
15511551
int bidx = 0;
15521552
bool is_hole;
1553+
bool lfs_dio_write;
15531554

15541555
if (!maxblocks)
15551556
return 0;
15561557

1558+
lfs_dio_write = (flag == F2FS_GET_BLOCK_DIO && f2fs_lfs_mode(sbi) &&
1559+
map->m_may_create);
1560+
15571561
if (!map->m_may_create && f2fs_map_blocks_cached(inode, map, flag))
15581562
goto out;
15591563

@@ -1600,7 +1604,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag)
16001604
/* use out-place-update for direct IO under LFS mode */
16011605
if (map->m_may_create && (is_hole ||
16021606
(flag == F2FS_GET_BLOCK_DIO && f2fs_lfs_mode(sbi) &&
1603-
!f2fs_is_pinned_file(inode)))) {
1607+
!f2fs_is_pinned_file(inode) && map->m_last_pblk != blkaddr))) {
16041608
if (unlikely(f2fs_cp_error(sbi))) {
16051609
err = -EIO;
16061610
goto sync_out;
@@ -1684,10 +1688,15 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag)
16841688

16851689
if (map->m_multidev_dio)
16861690
map->m_bdev = FDEV(bidx).bdev;
1691+
1692+
if (lfs_dio_write)
1693+
map->m_last_pblk = NULL_ADDR;
16871694
} else if (map_is_mergeable(sbi, map, blkaddr, flag, bidx, ofs)) {
16881695
ofs++;
16891696
map->m_len++;
16901697
} else {
1698+
if (lfs_dio_write && !f2fs_is_pinned_file(inode))
1699+
map->m_last_pblk = blkaddr;
16911700
goto sync_out;
16921701
}
16931702

@@ -1712,14 +1721,6 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag)
17121721
dn.ofs_in_node = end_offset;
17131722
}
17141723

1715-
if (flag == F2FS_GET_BLOCK_DIO && f2fs_lfs_mode(sbi) &&
1716-
map->m_may_create) {
1717-
/* the next block to be allocated may not be contiguous. */
1718-
if (GET_SEGOFF_FROM_SEG0(sbi, blkaddr) % BLKS_PER_SEC(sbi) ==
1719-
CAP_BLKS_PER_SEC(sbi) - 1)
1720-
goto sync_out;
1721-
}
1722-
17231724
if (pgofs >= end)
17241725
goto sync_out;
17251726
else if (dn.ofs_in_node < end_offset)
@@ -4162,7 +4163,7 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
41624163
unsigned int flags, struct iomap *iomap,
41634164
struct iomap *srcmap)
41644165
{
4165-
struct f2fs_map_blocks map = {};
4166+
struct f2fs_map_blocks map = { NULL, };
41664167
pgoff_t next_pgofs = 0;
41674168
int err;
41684169

@@ -4171,6 +4172,10 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
41714172
map.m_next_pgofs = &next_pgofs;
41724173
map.m_seg_type = f2fs_rw_hint_to_seg_type(F2FS_I_SB(inode),
41734174
inode->i_write_hint);
4175+
if (flags & IOMAP_WRITE && iomap->private) {
4176+
map.m_last_pblk = (unsigned long)iomap->private;
4177+
iomap->private = NULL;
4178+
}
41744179

41754180
/*
41764181
* If the blocks being overwritten are already allocated,
@@ -4209,6 +4214,9 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
42094214
iomap->flags |= IOMAP_F_MERGED;
42104215
iomap->bdev = map.m_bdev;
42114216
iomap->addr = F2FS_BLK_TO_BYTES(map.m_pblk);
4217+
4218+
if (flags & IOMAP_WRITE && map.m_last_pblk)
4219+
iomap->private = (void *)map.m_last_pblk;
42124220
} else {
42134221
if (flags & IOMAP_WRITE)
42144222
return -ENOTBLK;

fs/f2fs/f2fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,7 @@ struct f2fs_map_blocks {
732732
block_t m_lblk;
733733
unsigned int m_len;
734734
unsigned int m_flags;
735+
unsigned long m_last_pblk; /* last allocated block, only used for DIO in LFS mode */
735736
pgoff_t *m_next_pgofs; /* point next possible non-hole pgofs */
736737
pgoff_t *m_next_extent; /* point to next possible extent */
737738
int m_seg_type;

0 commit comments

Comments
 (0)