mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-07 13:43:51 +00:00
Btrfs: don't flush all delalloc inodes when we doesn't get s_umount lock
We needn't flush all delalloc inodes when we doesn't get s_umount lock, or we would make the tasks wait for a long time. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fb.com>
This commit is contained in:
parent
24af7dd188
commit
6c255e67ce
@ -3740,7 +3740,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
|
||||
u32 min_type);
|
||||
|
||||
int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput);
|
||||
int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput);
|
||||
int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput,
|
||||
int nr);
|
||||
int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,
|
||||
struct extent_state **cached_state);
|
||||
int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
|
||||
|
@ -491,7 +491,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
||||
* flush all outstanding I/O and inode extent mappings before the
|
||||
* copy operation is declared as being finished
|
||||
*/
|
||||
ret = btrfs_start_delalloc_roots(root->fs_info, 0);
|
||||
ret = btrfs_start_delalloc_roots(root->fs_info, 0, -1);
|
||||
if (ret) {
|
||||
mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
|
||||
return ret;
|
||||
|
@ -3971,7 +3971,7 @@ static int can_overcommit(struct btrfs_root *root,
|
||||
}
|
||||
|
||||
static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root,
|
||||
unsigned long nr_pages)
|
||||
unsigned long nr_pages, int nr_items)
|
||||
{
|
||||
struct super_block *sb = root->fs_info->sb;
|
||||
|
||||
@ -3986,9 +3986,9 @@ static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root,
|
||||
* the filesystem is readonly(all dirty pages are written to
|
||||
* the disk).
|
||||
*/
|
||||
btrfs_start_delalloc_roots(root->fs_info, 0);
|
||||
btrfs_start_delalloc_roots(root->fs_info, 0, nr_items);
|
||||
if (!current->journal_info)
|
||||
btrfs_wait_ordered_roots(root->fs_info, -1);
|
||||
btrfs_wait_ordered_roots(root->fs_info, nr_items);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4045,7 +4045,7 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
|
||||
while (delalloc_bytes && loops < 3) {
|
||||
max_reclaim = min(delalloc_bytes, to_reclaim);
|
||||
nr_pages = max_reclaim >> PAGE_CACHE_SHIFT;
|
||||
btrfs_writeback_inodes_sb_nr(root, nr_pages);
|
||||
btrfs_writeback_inodes_sb_nr(root, nr_pages, items);
|
||||
/*
|
||||
* We need to wait for the async pages to actually start before
|
||||
* we do anything.
|
||||
|
@ -8437,7 +8437,8 @@ void btrfs_wait_and_free_delalloc_work(struct btrfs_delalloc_work *work)
|
||||
* some fairly slow code that needs optimization. This walks the list
|
||||
* of all the inodes with pending delalloc and forces them to disk.
|
||||
*/
|
||||
static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
|
||||
static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput,
|
||||
int nr)
|
||||
{
|
||||
struct btrfs_inode *binode;
|
||||
struct inode *inode;
|
||||
@ -8471,23 +8472,19 @@ static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
|
||||
else
|
||||
iput(inode);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
list_add_tail(&work->list, &works);
|
||||
btrfs_queue_work(root->fs_info->flush_workers,
|
||||
&work->work);
|
||||
|
||||
ret++;
|
||||
if (nr != -1 && ret >= nr)
|
||||
break;
|
||||
cond_resched();
|
||||
spin_lock(&root->delalloc_lock);
|
||||
}
|
||||
spin_unlock(&root->delalloc_lock);
|
||||
|
||||
list_for_each_entry_safe(work, next, &works, list) {
|
||||
list_del_init(&work->list);
|
||||
btrfs_wait_and_free_delalloc_work(work);
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
list_for_each_entry_safe(work, next, &works, list) {
|
||||
list_del_init(&work->list);
|
||||
btrfs_wait_and_free_delalloc_work(work);
|
||||
@ -8508,7 +8505,9 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
|
||||
if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state))
|
||||
return -EROFS;
|
||||
|
||||
ret = __start_delalloc_inodes(root, delay_iput);
|
||||
ret = __start_delalloc_inodes(root, delay_iput, -1);
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
/*
|
||||
* the filemap_flush will queue IO into the worker threads, but
|
||||
* we have to make sure the IO is actually started and that
|
||||
@ -8525,7 +8524,8 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput)
|
||||
int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput,
|
||||
int nr)
|
||||
{
|
||||
struct btrfs_root *root;
|
||||
struct list_head splice;
|
||||
@ -8538,7 +8538,7 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput)
|
||||
|
||||
spin_lock(&fs_info->delalloc_root_lock);
|
||||
list_splice_init(&fs_info->delalloc_roots, &splice);
|
||||
while (!list_empty(&splice)) {
|
||||
while (!list_empty(&splice) && nr) {
|
||||
root = list_first_entry(&splice, struct btrfs_root,
|
||||
delalloc_root);
|
||||
root = btrfs_grab_fs_root(root);
|
||||
@ -8547,15 +8547,20 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput)
|
||||
&fs_info->delalloc_roots);
|
||||
spin_unlock(&fs_info->delalloc_root_lock);
|
||||
|
||||
ret = __start_delalloc_inodes(root, delay_iput);
|
||||
ret = __start_delalloc_inodes(root, delay_iput, nr);
|
||||
btrfs_put_fs_root(root);
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (nr != -1) {
|
||||
nr -= ret;
|
||||
WARN_ON(nr < 0);
|
||||
}
|
||||
spin_lock(&fs_info->delalloc_root_lock);
|
||||
}
|
||||
spin_unlock(&fs_info->delalloc_root_lock);
|
||||
|
||||
ret = 0;
|
||||
atomic_inc(&fs_info->async_submit_draining);
|
||||
while (atomic_read(&fs_info->nr_async_submits) ||
|
||||
atomic_read(&fs_info->async_delalloc_pages)) {
|
||||
@ -8564,7 +8569,6 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput)
|
||||
atomic_read(&fs_info->async_delalloc_pages) == 0));
|
||||
}
|
||||
atomic_dec(&fs_info->async_submit_draining);
|
||||
return 0;
|
||||
out:
|
||||
if (!list_empty_careful(&splice)) {
|
||||
spin_lock(&fs_info->delalloc_root_lock);
|
||||
|
@ -4893,7 +4893,7 @@ long btrfs_ioctl(struct file *file, unsigned int
|
||||
case BTRFS_IOC_SYNC: {
|
||||
int ret;
|
||||
|
||||
ret = btrfs_start_delalloc_roots(root->fs_info, 0);
|
||||
ret = btrfs_start_delalloc_roots(root->fs_info, 0, -1);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = btrfs_sync_fs(file->f_dentry->d_sb, 1);
|
||||
|
@ -4248,7 +4248,7 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
|
||||
btrfs_info(extent_root->fs_info, "relocating block group %llu flags %llu",
|
||||
rc->block_group->key.objectid, rc->block_group->flags);
|
||||
|
||||
ret = btrfs_start_delalloc_roots(fs_info, 0);
|
||||
ret = btrfs_start_delalloc_roots(fs_info, 0, -1);
|
||||
if (ret < 0) {
|
||||
err = ret;
|
||||
goto out;
|
||||
|
@ -1620,7 +1620,7 @@ static int btrfs_flush_all_pending_stuffs(struct btrfs_trans_handle *trans,
|
||||
static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
if (btrfs_test_opt(fs_info->tree_root, FLUSHONCOMMIT))
|
||||
return btrfs_start_delalloc_roots(fs_info, 1);
|
||||
return btrfs_start_delalloc_roots(fs_info, 1, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user