Commit df2825e9 authored by David Sterba's avatar David Sterba

btrfs: always pass readahead state to defrag

Defrag ioctl passes readahead from the file, but autodefrag does not
have a file so the readahead state is allocated when needed.

The autodefrag loop in cleaner thread iterates over inodes so we can
simply provide an on-stack readahead state and will not need to allocate
it in btrfs_defrag_file(). The size is 32 bytes which is acceptable.
Reviewed-by: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 11e3107d
...@@ -219,7 +219,8 @@ void btrfs_cleanup_defrag_inodes(struct btrfs_fs_info *fs_info) ...@@ -219,7 +219,8 @@ void btrfs_cleanup_defrag_inodes(struct btrfs_fs_info *fs_info)
#define BTRFS_DEFRAG_BATCH 1024 #define BTRFS_DEFRAG_BATCH 1024
static int btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, static int btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
struct inode_defrag *defrag) struct inode_defrag *defrag,
struct file_ra_state *ra)
{ {
struct btrfs_root *inode_root; struct btrfs_root *inode_root;
struct inode *inode; struct inode *inode;
...@@ -258,9 +259,10 @@ static int btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info, ...@@ -258,9 +259,10 @@ static int btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
range.len = (u64)-1; range.len = (u64)-1;
range.start = cur; range.start = cur;
range.extent_thresh = defrag->extent_thresh; range.extent_thresh = defrag->extent_thresh;
file_ra_state_init(ra, inode->i_mapping);
sb_start_write(fs_info->sb); sb_start_write(fs_info->sb);
ret = btrfs_defrag_file(inode, NULL, &range, defrag->transid, ret = btrfs_defrag_file(inode, ra, &range, defrag->transid,
BTRFS_DEFRAG_BATCH); BTRFS_DEFRAG_BATCH);
sb_end_write(fs_info->sb); sb_end_write(fs_info->sb);
iput(inode); iput(inode);
...@@ -287,6 +289,8 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info) ...@@ -287,6 +289,8 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
atomic_inc(&fs_info->defrag_running); atomic_inc(&fs_info->defrag_running);
while (1) { while (1) {
struct file_ra_state ra = { 0 };
/* Pause the auto defragger. */ /* Pause the auto defragger. */
if (test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state)) if (test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state))
break; break;
...@@ -309,7 +313,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info) ...@@ -309,7 +313,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
first_ino = defrag->ino + 1; first_ino = defrag->ino + 1;
root_objectid = defrag->root; root_objectid = defrag->root;
btrfs_run_defrag_inode(fs_info, defrag); btrfs_run_defrag_inode(fs_info, defrag, &ra);
} }
atomic_dec(&fs_info->defrag_running); atomic_dec(&fs_info->defrag_running);
...@@ -1302,7 +1306,6 @@ static int defrag_one_cluster(struct btrfs_inode *inode, ...@@ -1302,7 +1306,6 @@ static int defrag_one_cluster(struct btrfs_inode *inode,
if (entry->start + range_len <= *last_scanned_ret) if (entry->start + range_len <= *last_scanned_ret)
continue; continue;
if (ra)
page_cache_sync_readahead(inode->vfs_inode.i_mapping, page_cache_sync_readahead(inode->vfs_inode.i_mapping,
ra, NULL, entry->start >> PAGE_SHIFT, ra, NULL, entry->start >> PAGE_SHIFT,
((entry->start + range_len - 1) >> PAGE_SHIFT) - ((entry->start + range_len - 1) >> PAGE_SHIFT) -
...@@ -1335,7 +1338,7 @@ static int defrag_one_cluster(struct btrfs_inode *inode, ...@@ -1335,7 +1338,7 @@ static int defrag_one_cluster(struct btrfs_inode *inode,
* Entry point to file defragmentation. * Entry point to file defragmentation.
* *
* @inode: inode to be defragged * @inode: inode to be defragged
* @ra: readahead state (can be NUL) * @ra: readahead state
* @range: defrag options including range and flags * @range: defrag options including range and flags
* @newer_than: minimum transid to defrag * @newer_than: minimum transid to defrag
* @max_to_defrag: max number of sectors to be defragged, if 0, the whole inode * @max_to_defrag: max number of sectors to be defragged, if 0, the whole inode
...@@ -1357,12 +1360,13 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra, ...@@ -1357,12 +1360,13 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra,
u64 cur; u64 cur;
u64 last_byte; u64 last_byte;
bool do_compress = (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS); bool do_compress = (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS);
bool ra_allocated = false;
int compress_type = BTRFS_COMPRESS_ZLIB; int compress_type = BTRFS_COMPRESS_ZLIB;
int ret = 0; int ret = 0;
u32 extent_thresh = range->extent_thresh; u32 extent_thresh = range->extent_thresh;
pgoff_t start_index; pgoff_t start_index;
ASSERT(ra);
if (isize == 0) if (isize == 0)
return 0; return 0;
...@@ -1391,18 +1395,6 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra, ...@@ -1391,18 +1395,6 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra,
cur = round_down(range->start, fs_info->sectorsize); cur = round_down(range->start, fs_info->sectorsize);
last_byte = round_up(last_byte, fs_info->sectorsize) - 1; last_byte = round_up(last_byte, fs_info->sectorsize) - 1;
/*
* If we were not given a ra, allocate a readahead context. As
* readahead is just an optimization, defrag will work without it so
* we don't error out.
*/
if (!ra) {
ra_allocated = true;
ra = kzalloc(sizeof(*ra), GFP_KERNEL);
if (ra)
file_ra_state_init(ra, inode->i_mapping);
}
/* /*
* Make writeback start from the beginning of the range, so that the * Make writeback start from the beginning of the range, so that the
* defrag range can be written sequentially. * defrag range can be written sequentially.
...@@ -1457,8 +1449,6 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra, ...@@ -1457,8 +1449,6 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra,
cond_resched(); cond_resched();
} }
if (ra_allocated)
kfree(ra);
/* /*
* Update range.start for autodefrag, this will indicate where to start * Update range.start for autodefrag, this will indicate where to start
* in next run. * in next run.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment