Skip to content

Commit 558732d

Browse files
adam900710kdave
authored andcommitted
btrfs: reduce extent threshold for autodefrag
There is a big gap between inode_should_defrag() and autodefrag extent size threshold. For inode_should_defrag() it has a flexible @small_write value. For compressed extent is 16K, and for non-compressed extent it's 64K. However for autodefrag extent size threshold, it's always fixed to the default value (256K). This means, the following write sequence will trigger autodefrag to defrag ranges which didn't trigger autodefrag: pwrite 0 8k sync pwrite 8k 128K sync The latter 128K write will also be considered as a defrag target (if other conditions are met). While only that 8K write is really triggering autodefrag. Such behavior can cause extra IO for autodefrag. Close the gap, by copying the @small_write value into inode_defrag, so that later autodefrag can use the same @small_write value which triggered autodefrag. With the existing transid value, this allows autodefrag really to scan the ranges which triggered autodefrag. Although this behavior change is mostly reducing the extent_thresh value for autodefrag, I believe in the future we should allow users to specify the autodefrag extent threshold through mount options, but that's an other problem to consider in the future. CC: [email protected] # 5.16+ Signed-off-by: Qu Wenruo <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 26fbac2 commit 558732d

File tree

3 files changed

+17
-4
lines changed

3 files changed

+17
-4
lines changed

fs/btrfs/ctree.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3291,7 +3291,7 @@ void btrfs_exclop_balance(struct btrfs_fs_info *fs_info,
32913291
int __init btrfs_auto_defrag_init(void);
32923292
void __cold btrfs_auto_defrag_exit(void);
32933293
int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
3294-
struct btrfs_inode *inode);
3294+
struct btrfs_inode *inode, u32 extent_thresh);
32953295
int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info);
32963296
void btrfs_cleanup_defrag_inodes(struct btrfs_fs_info *fs_info);
32973297
int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync);

fs/btrfs/file.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ struct inode_defrag {
4949

5050
/* root objectid */
5151
u64 root;
52+
53+
/*
54+
* The extent size threshold for autodefrag.
55+
*
56+
* This value is different for compressed/non-compressed extents,
57+
* thus needs to be passed from higher layer.
58+
* (aka, inode_should_defrag())
59+
*/
60+
u32 extent_thresh;
5261
};
5362

5463
static int __compare_inode_defrag(struct inode_defrag *defrag1,
@@ -101,6 +110,8 @@ static int __btrfs_add_inode_defrag(struct btrfs_inode *inode,
101110
*/
102111
if (defrag->transid < entry->transid)
103112
entry->transid = defrag->transid;
113+
entry->extent_thresh = min(defrag->extent_thresh,
114+
entry->extent_thresh);
104115
return -EEXIST;
105116
}
106117
}
@@ -126,7 +137,7 @@ static inline int __need_auto_defrag(struct btrfs_fs_info *fs_info)
126137
* enabled
127138
*/
128139
int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
129-
struct btrfs_inode *inode)
140+
struct btrfs_inode *inode, u32 extent_thresh)
130141
{
131142
struct btrfs_root *root = inode->root;
132143
struct btrfs_fs_info *fs_info = root->fs_info;
@@ -152,6 +163,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
152163
defrag->ino = btrfs_ino(inode);
153164
defrag->transid = transid;
154165
defrag->root = root->root_key.objectid;
166+
defrag->extent_thresh = extent_thresh;
155167

156168
spin_lock(&fs_info->defrag_inodes_lock);
157169
if (!test_bit(BTRFS_INODE_IN_DEFRAG, &inode->runtime_flags)) {
@@ -275,6 +287,7 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
275287
memset(&range, 0, sizeof(range));
276288
range.len = (u64)-1;
277289
range.start = cur;
290+
range.extent_thresh = defrag->extent_thresh;
278291

279292
sb_start_write(fs_info->sb);
280293
ret = btrfs_defrag_file(inode, NULL, &range, defrag->transid,

fs/btrfs/inode.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,12 +560,12 @@ static inline int inode_need_compress(struct btrfs_inode *inode, u64 start,
560560
}
561561

562562
static inline void inode_should_defrag(struct btrfs_inode *inode,
563-
u64 start, u64 end, u64 num_bytes, u64 small_write)
563+
u64 start, u64 end, u64 num_bytes, u32 small_write)
564564
{
565565
/* If this is a small write inside eof, kick off a defrag */
566566
if (num_bytes < small_write &&
567567
(start > 0 || end + 1 < inode->disk_i_size))
568-
btrfs_add_inode_defrag(NULL, inode);
568+
btrfs_add_inode_defrag(NULL, inode, small_write);
569569
}
570570

571571
/*

0 commit comments

Comments
 (0)