Commit 6c255e67 authored by Miao Xie's avatar Miao Xie Committed by Josef Bacik

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: default avatarMiao Xie <miaox@cn.fujitsu.com>
Signed-off-by: default avatarJosef Bacik <jbacik@fb.com>
parent 24af7dd1
...@@ -3740,7 +3740,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, ...@@ -3740,7 +3740,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
u32 min_type); u32 min_type);
int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput); 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, int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,
struct extent_state **cached_state); struct extent_state **cached_state);
int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, 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, ...@@ -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 * flush all outstanding I/O and inode extent mappings before the
* copy operation is declared as being finished * 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) { if (ret) {
mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
return ret; return ret;
......
...@@ -3971,7 +3971,7 @@ static int can_overcommit(struct btrfs_root *root, ...@@ -3971,7 +3971,7 @@ static int can_overcommit(struct btrfs_root *root,
} }
static void btrfs_writeback_inodes_sb_nr(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; struct super_block *sb = root->fs_info->sb;
...@@ -3986,9 +3986,9 @@ static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root, ...@@ -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 filesystem is readonly(all dirty pages are written to
* the disk). * the disk).
*/ */
btrfs_start_delalloc_roots(root->fs_info, 0); btrfs_start_delalloc_roots(root->fs_info, 0, nr_items);
if (!current->journal_info) 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, ...@@ -4045,7 +4045,7 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
while (delalloc_bytes && loops < 3) { while (delalloc_bytes && loops < 3) {
max_reclaim = min(delalloc_bytes, to_reclaim); max_reclaim = min(delalloc_bytes, to_reclaim);
nr_pages = max_reclaim >> PAGE_CACHE_SHIFT; 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 need to wait for the async pages to actually start before
* we do anything. * we do anything.
......
...@@ -8437,7 +8437,8 @@ void btrfs_wait_and_free_delalloc_work(struct btrfs_delalloc_work *work) ...@@ -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 * some fairly slow code that needs optimization. This walks the list
* of all the inodes with pending delalloc and forces them to disk. * 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 btrfs_inode *binode;
struct inode *inode; struct inode *inode;
...@@ -8471,23 +8472,19 @@ static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput) ...@@ -8471,23 +8472,19 @@ static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
else else
iput(inode); iput(inode);
ret = -ENOMEM; ret = -ENOMEM;
goto out; break;
} }
list_add_tail(&work->list, &works); list_add_tail(&work->list, &works);
btrfs_queue_work(root->fs_info->flush_workers, btrfs_queue_work(root->fs_info->flush_workers,
&work->work); &work->work);
ret++;
if (nr != -1 && ret >= nr)
break;
cond_resched(); cond_resched();
spin_lock(&root->delalloc_lock); spin_lock(&root->delalloc_lock);
} }
spin_unlock(&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_for_each_entry_safe(work, next, &works, list) {
list_del_init(&work->list); list_del_init(&work->list);
btrfs_wait_and_free_delalloc_work(work); btrfs_wait_and_free_delalloc_work(work);
...@@ -8508,7 +8505,9 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput) ...@@ -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)) if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state))
return -EROFS; 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 * the filemap_flush will queue IO into the worker threads, but
* we have to make sure the IO is actually started and that * 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) ...@@ -8525,7 +8524,8 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
return ret; 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 btrfs_root *root;
struct list_head splice; struct list_head splice;
...@@ -8538,7 +8538,7 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput) ...@@ -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); spin_lock(&fs_info->delalloc_root_lock);
list_splice_init(&fs_info->delalloc_roots, &splice); 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, root = list_first_entry(&splice, struct btrfs_root,
delalloc_root); delalloc_root);
root = btrfs_grab_fs_root(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) ...@@ -8547,15 +8547,20 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, int delay_iput)
&fs_info->delalloc_roots); &fs_info->delalloc_roots);
spin_unlock(&fs_info->delalloc_root_lock); 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); btrfs_put_fs_root(root);
if (ret) if (ret < 0)
goto out; goto out;
if (nr != -1) {
nr -= ret;
WARN_ON(nr < 0);
}
spin_lock(&fs_info->delalloc_root_lock); spin_lock(&fs_info->delalloc_root_lock);
} }
spin_unlock(&fs_info->delalloc_root_lock); spin_unlock(&fs_info->delalloc_root_lock);
ret = 0;
atomic_inc(&fs_info->async_submit_draining); atomic_inc(&fs_info->async_submit_draining);
while (atomic_read(&fs_info->nr_async_submits) || while (atomic_read(&fs_info->nr_async_submits) ||
atomic_read(&fs_info->async_delalloc_pages)) { 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) ...@@ -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_read(&fs_info->async_delalloc_pages) == 0));
} }
atomic_dec(&fs_info->async_submit_draining); atomic_dec(&fs_info->async_submit_draining);
return 0;
out: out:
if (!list_empty_careful(&splice)) { if (!list_empty_careful(&splice)) {
spin_lock(&fs_info->delalloc_root_lock); spin_lock(&fs_info->delalloc_root_lock);
......
...@@ -4893,7 +4893,7 @@ long btrfs_ioctl(struct file *file, unsigned int ...@@ -4893,7 +4893,7 @@ long btrfs_ioctl(struct file *file, unsigned int
case BTRFS_IOC_SYNC: { case BTRFS_IOC_SYNC: {
int ret; int ret;
ret = btrfs_start_delalloc_roots(root->fs_info, 0); ret = btrfs_start_delalloc_roots(root->fs_info, 0, -1);
if (ret) if (ret)
return ret; return ret;
ret = btrfs_sync_fs(file->f_dentry->d_sb, 1); 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) ...@@ -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", btrfs_info(extent_root->fs_info, "relocating block group %llu flags %llu",
rc->block_group->key.objectid, rc->block_group->flags); 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) { if (ret < 0) {
err = ret; err = ret;
goto out; goto out;
......
...@@ -1620,7 +1620,7 @@ static int btrfs_flush_all_pending_stuffs(struct btrfs_trans_handle *trans, ...@@ -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) static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info)
{ {
if (btrfs_test_opt(fs_info->tree_root, FLUSHONCOMMIT)) 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; return 0;
} }
......
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