Skip to content

Commit d8101a0

Browse files
adam900710kdave
authored andcommitted
btrfs: allow defrag to convert inline extents to regular extents
Btrfs defaults to max_inline=2K to make small writes inlined into metadata. The default value is always a win, as even DUP/RAID1/RAID10 doubles the metadata usage, it should still cause less physical space used compared to a 4K regular extents. But since the introduction of RAID1C3 and RAID1C4 it's no longer the case, users may find inlined extents causing too much space wasted, and want to convert those inlined extents back to regular extents. Unfortunately defrag will unconditionally skip all inline extents, no matter if the user is trying to converting them back to regular extents. So this patch will add a small exception for defrag_collect_targets() to allow defragging inline extents, if and only if the inlined extents are larger than max_inline, allowing users to convert them to regular ones. This also allows us to defrag extents like the following: item 6 key (257 EXTENT_DATA 0) itemoff 15794 itemsize 69 generation 7 type 0 (inline) inline extent data size 48 ram_bytes 4096 compression 1 (zlib) item 7 key (257 EXTENT_DATA 4096) itemoff 15741 itemsize 53 generation 7 type 1 (regular) extent data disk byte 13631488 nr 4096 extent data offset 0 nr 16384 ram 16384 extent compression 1 (zlib) Previously we're unable to do any defrag, since the first extent is inlined, and the second one has no extent to merge. Now we can defrag it to just one single extent, saving 48 bytes metadata space. item 6 key (257 EXTENT_DATA 0) itemoff 15810 itemsize 53 generation 8 type 1 (regular) extent data disk byte 13635584 nr 4096 extent data offset 0 nr 20480 ram 20480 extent compression 1 (zlib) Reviewed-by: Filipe Manana <[email protected]> Signed-off-by: Qu Wenruo <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent d5321a0 commit d8101a0

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

fs/btrfs/ioctl.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,8 +1420,19 @@ static int defrag_collect_targets(struct btrfs_inode *inode,
14201420
if (!em)
14211421
break;
14221422

1423-
/* Skip hole/inline/preallocated extents */
1424-
if (em->block_start >= EXTENT_MAP_LAST_BYTE ||
1423+
/*
1424+
* If the file extent is an inlined one, we may still want to
1425+
* defrag it (fallthrough) if it will cause a regular extent.
1426+
* This is for users who want to convert inline extents to
1427+
* regular ones through max_inline= mount option.
1428+
*/
1429+
if (em->block_start == EXTENT_MAP_INLINE &&
1430+
em->len <= inode->root->fs_info->max_inline)
1431+
goto next;
1432+
1433+
/* Skip hole/delalloc/preallocated extents */
1434+
if (em->block_start == EXTENT_MAP_HOLE ||
1435+
em->block_start == EXTENT_MAP_DELALLOC ||
14251436
test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
14261437
goto next;
14271438

@@ -1480,6 +1491,15 @@ static int defrag_collect_targets(struct btrfs_inode *inode,
14801491
if (em->len >= get_extent_max_capacity(em))
14811492
goto next;
14821493

1494+
/*
1495+
* Normally there are no more extents after an inline one, thus
1496+
* @next_mergeable will normally be false and not defragged.
1497+
* So if an inline extent passed all above checks, just add it
1498+
* for defrag, and be converted to regular extents.
1499+
*/
1500+
if (em->block_start == EXTENT_MAP_INLINE)
1501+
goto add;
1502+
14831503
next_mergeable = defrag_check_next_extent(&inode->vfs_inode, em,
14841504
extent_thresh, newer_than, locked);
14851505
if (!next_mergeable) {

0 commit comments

Comments
 (0)