aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h14
-rw-r--r--fs/btrfs/disk-io.c7
-rw-r--r--fs/btrfs/inode.c78
-rw-r--r--fs/btrfs/relocation.c6
-rw-r--r--fs/btrfs/transaction.c6
5 files changed, 103 insertions, 8 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 8fd9fe4282f5..cad16566da37 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1333,6 +1333,7 @@ struct btrfs_fs_info {
1333 struct btrfs_workers generic_worker; 1333 struct btrfs_workers generic_worker;
1334 struct btrfs_workers workers; 1334 struct btrfs_workers workers;
1335 struct btrfs_workers delalloc_workers; 1335 struct btrfs_workers delalloc_workers;
1336 struct btrfs_workers flush_workers;
1336 struct btrfs_workers endio_workers; 1337 struct btrfs_workers endio_workers;
1337 struct btrfs_workers endio_meta_workers; 1338 struct btrfs_workers endio_meta_workers;
1338 struct btrfs_workers endio_meta_write_workers; 1339 struct btrfs_workers endio_meta_write_workers;
@@ -3277,6 +3278,19 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
3277int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, 3278int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
3278 struct list_head *list, int search_commit); 3279 struct list_head *list, int search_commit);
3279/* inode.c */ 3280/* inode.c */
3281struct btrfs_delalloc_work {
3282 struct inode *inode;
3283 int wait;
3284 int delay_iput;
3285 struct completion completion;
3286 struct list_head list;
3287 struct btrfs_work work;
3288};
3289
3290struct btrfs_delalloc_work *btrfs_alloc_delalloc_work(struct inode *inode,
3291 int wait, int delay_iput);
3292void btrfs_wait_and_free_delalloc_work(struct btrfs_delalloc_work *work);
3293
3280struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *page, 3294struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *page,
3281 size_t pg_offset, u64 start, u64 len, 3295 size_t pg_offset, u64 start, u64 len,
3282 int create); 3296 int create);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 7cda51995c1e..bd70c2852ba0 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2279,6 +2279,10 @@ int open_ctree(struct super_block *sb,
2279 fs_info->thread_pool_size, 2279 fs_info->thread_pool_size,
2280 &fs_info->generic_worker); 2280 &fs_info->generic_worker);
2281 2281
2282 btrfs_init_workers(&fs_info->flush_workers, "flush_delalloc",
2283 fs_info->thread_pool_size,
2284 &fs_info->generic_worker);
2285
2282 btrfs_init_workers(&fs_info->submit_workers, "submit", 2286 btrfs_init_workers(&fs_info->submit_workers, "submit",
2283 min_t(u64, fs_devices->num_devices, 2287 min_t(u64, fs_devices->num_devices,
2284 fs_info->thread_pool_size), 2288 fs_info->thread_pool_size),
@@ -2350,6 +2354,7 @@ int open_ctree(struct super_block *sb,
2350 ret |= btrfs_start_workers(&fs_info->delayed_workers); 2354 ret |= btrfs_start_workers(&fs_info->delayed_workers);
2351 ret |= btrfs_start_workers(&fs_info->caching_workers); 2355 ret |= btrfs_start_workers(&fs_info->caching_workers);
2352 ret |= btrfs_start_workers(&fs_info->readahead_workers); 2356 ret |= btrfs_start_workers(&fs_info->readahead_workers);
2357 ret |= btrfs_start_workers(&fs_info->flush_workers);
2353 if (ret) { 2358 if (ret) {
2354 err = -ENOMEM; 2359 err = -ENOMEM;
2355 goto fail_sb_buffer; 2360 goto fail_sb_buffer;
@@ -2667,6 +2672,7 @@ fail_sb_buffer:
2667 btrfs_stop_workers(&fs_info->submit_workers); 2672 btrfs_stop_workers(&fs_info->submit_workers);
2668 btrfs_stop_workers(&fs_info->delayed_workers); 2673 btrfs_stop_workers(&fs_info->delayed_workers);
2669 btrfs_stop_workers(&fs_info->caching_workers); 2674 btrfs_stop_workers(&fs_info->caching_workers);
2675 btrfs_stop_workers(&fs_info->flush_workers);
2670fail_alloc: 2676fail_alloc:
2671fail_iput: 2677fail_iput:
2672 btrfs_mapping_tree_free(&fs_info->mapping_tree); 2678 btrfs_mapping_tree_free(&fs_info->mapping_tree);
@@ -3339,6 +3345,7 @@ int close_ctree(struct btrfs_root *root)
3339 btrfs_stop_workers(&fs_info->delayed_workers); 3345 btrfs_stop_workers(&fs_info->delayed_workers);
3340 btrfs_stop_workers(&fs_info->caching_workers); 3346 btrfs_stop_workers(&fs_info->caching_workers);
3341 btrfs_stop_workers(&fs_info->readahead_workers); 3347 btrfs_stop_workers(&fs_info->readahead_workers);
3348 btrfs_stop_workers(&fs_info->flush_workers);
3342 3349
3343#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY 3350#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
3344 if (btrfs_test_opt(root, CHECK_INTEGRITY)) 3351 if (btrfs_test_opt(root, CHECK_INTEGRITY))
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index db3dd4ed057f..dce9e218b845 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -71,6 +71,7 @@ static const struct file_operations btrfs_dir_file_operations;
71static struct extent_io_ops btrfs_extent_io_ops; 71static struct extent_io_ops btrfs_extent_io_ops;
72 72
73static struct kmem_cache *btrfs_inode_cachep; 73static struct kmem_cache *btrfs_inode_cachep;
74static struct kmem_cache *btrfs_delalloc_work_cachep;
74struct kmem_cache *btrfs_trans_handle_cachep; 75struct kmem_cache *btrfs_trans_handle_cachep;
75struct kmem_cache *btrfs_transaction_cachep; 76struct kmem_cache *btrfs_transaction_cachep;
76struct kmem_cache *btrfs_path_cachep; 77struct kmem_cache *btrfs_path_cachep;
@@ -7204,6 +7205,8 @@ void btrfs_destroy_cachep(void)
7204 kmem_cache_destroy(btrfs_path_cachep); 7205 kmem_cache_destroy(btrfs_path_cachep);
7205 if (btrfs_free_space_cachep) 7206 if (btrfs_free_space_cachep)
7206 kmem_cache_destroy(btrfs_free_space_cachep); 7207 kmem_cache_destroy(btrfs_free_space_cachep);
7208 if (btrfs_delalloc_work_cachep)
7209 kmem_cache_destroy(btrfs_delalloc_work_cachep);
7207} 7210}
7208 7211
7209int btrfs_init_cachep(void) 7212int btrfs_init_cachep(void)
@@ -7238,6 +7241,13 @@ int btrfs_init_cachep(void)
7238 if (!btrfs_free_space_cachep) 7241 if (!btrfs_free_space_cachep)
7239 goto fail; 7242 goto fail;
7240 7243
7244 btrfs_delalloc_work_cachep = kmem_cache_create("btrfs_delalloc_work",
7245 sizeof(struct btrfs_delalloc_work), 0,
7246 SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
7247 NULL);
7248 if (!btrfs_delalloc_work_cachep)
7249 goto fail;
7250
7241 return 0; 7251 return 0;
7242fail: 7252fail:
7243 btrfs_destroy_cachep(); 7253 btrfs_destroy_cachep();
@@ -7448,6 +7458,49 @@ out_notrans:
7448 return ret; 7458 return ret;
7449} 7459}
7450 7460
7461static void btrfs_run_delalloc_work(struct btrfs_work *work)
7462{
7463 struct btrfs_delalloc_work *delalloc_work;
7464
7465 delalloc_work = container_of(work, struct btrfs_delalloc_work,
7466 work);
7467 if (delalloc_work->wait)
7468 btrfs_wait_ordered_range(delalloc_work->inode, 0, (u64)-1);
7469 else
7470 filemap_flush(delalloc_work->inode->i_mapping);
7471
7472 if (delalloc_work->delay_iput)
7473 btrfs_add_delayed_iput(delalloc_work->inode);
7474 else
7475 iput(delalloc_work->inode);
7476 complete(&delalloc_work->completion);
7477}
7478
7479struct btrfs_delalloc_work *btrfs_alloc_delalloc_work(struct inode *inode,
7480 int wait, int delay_iput)
7481{
7482 struct btrfs_delalloc_work *work;
7483
7484 work = kmem_cache_zalloc(btrfs_delalloc_work_cachep, GFP_NOFS);
7485 if (!work)
7486 return NULL;
7487
7488 init_completion(&work->completion);
7489 INIT_LIST_HEAD(&work->list);
7490 work->inode = inode;
7491 work->wait = wait;
7492 work->delay_iput = delay_iput;
7493 work->work.func = btrfs_run_delalloc_work;
7494
7495 return work;
7496}
7497
7498void btrfs_wait_and_free_delalloc_work(struct btrfs_delalloc_work *work)
7499{
7500 wait_for_completion(&work->completion);
7501 kmem_cache_free(btrfs_delalloc_work_cachep, work);
7502}
7503
7451/* 7504/*
7452 * some fairly slow code that needs optimization. This walks the list 7505 * some fairly slow code that needs optimization. This walks the list
7453 * of all the inodes with pending delalloc and forces them to disk. 7506 * of all the inodes with pending delalloc and forces them to disk.
@@ -7457,10 +7510,15 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
7457 struct list_head *head = &root->fs_info->delalloc_inodes; 7510 struct list_head *head = &root->fs_info->delalloc_inodes;
7458 struct btrfs_inode *binode; 7511 struct btrfs_inode *binode;
7459 struct inode *inode; 7512 struct inode *inode;
7513 struct btrfs_delalloc_work *work, *next;
7514 struct list_head works;
7515 int ret = 0;
7460 7516
7461 if (root->fs_info->sb->s_flags & MS_RDONLY) 7517 if (root->fs_info->sb->s_flags & MS_RDONLY)
7462 return -EROFS; 7518 return -EROFS;
7463 7519
7520 INIT_LIST_HEAD(&works);
7521
7464 spin_lock(&root->fs_info->delalloc_lock); 7522 spin_lock(&root->fs_info->delalloc_lock);
7465 while (!list_empty(head)) { 7523 while (!list_empty(head)) {
7466 binode = list_entry(head->next, struct btrfs_inode, 7524 binode = list_entry(head->next, struct btrfs_inode,
@@ -7470,11 +7528,14 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
7470 list_del_init(&binode->delalloc_inodes); 7528 list_del_init(&binode->delalloc_inodes);
7471 spin_unlock(&root->fs_info->delalloc_lock); 7529 spin_unlock(&root->fs_info->delalloc_lock);
7472 if (inode) { 7530 if (inode) {
7473 filemap_flush(inode->i_mapping); 7531 work = btrfs_alloc_delalloc_work(inode, 0, delay_iput);
7474 if (delay_iput) 7532 if (!work) {
7475 btrfs_add_delayed_iput(inode); 7533 ret = -ENOMEM;
7476 else 7534 goto out;
7477 iput(inode); 7535 }
7536 list_add_tail(&work->list, &works);
7537 btrfs_queue_worker(&root->fs_info->flush_workers,
7538 &work->work);
7478 } 7539 }
7479 cond_resched(); 7540 cond_resched();
7480 spin_lock(&root->fs_info->delalloc_lock); 7541 spin_lock(&root->fs_info->delalloc_lock);
@@ -7493,7 +7554,12 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
7493 atomic_read(&root->fs_info->async_delalloc_pages) == 0)); 7554 atomic_read(&root->fs_info->async_delalloc_pages) == 0));
7494 } 7555 }
7495 atomic_dec(&root->fs_info->async_submit_draining); 7556 atomic_dec(&root->fs_info->async_submit_draining);
7496 return 0; 7557out:
7558 list_for_each_entry_safe(work, next, &works, list) {
7559 list_del_init(&work->list);
7560 btrfs_wait_and_free_delalloc_work(work);
7561 }
7562 return ret;
7497} 7563}
7498 7564
7499static int btrfs_symlink(struct inode *dir, struct dentry *dentry, 7565static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 242d6de4d8eb..270f24ffe1be 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -4061,7 +4061,11 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
4061 (unsigned long long)rc->block_group->key.objectid, 4061 (unsigned long long)rc->block_group->key.objectid,
4062 (unsigned long long)rc->block_group->flags); 4062 (unsigned long long)rc->block_group->flags);
4063 4063
4064 btrfs_start_delalloc_inodes(fs_info->tree_root, 0); 4064 ret = btrfs_start_delalloc_inodes(fs_info->tree_root, 0);
4065 if (ret < 0) {
4066 err = ret;
4067 goto out;
4068 }
4065 btrfs_wait_ordered_extents(fs_info->tree_root, 0); 4069 btrfs_wait_ordered_extents(fs_info->tree_root, 0);
4066 4070
4067 while (1) { 4071 while (1) {
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 4e1def4c06b1..9c466f9f8175 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1497,7 +1497,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1497 WARN_ON(cur_trans != trans->transaction); 1497 WARN_ON(cur_trans != trans->transaction);
1498 1498
1499 if (flush_on_commit || snap_pending) { 1499 if (flush_on_commit || snap_pending) {
1500 btrfs_start_delalloc_inodes(root, 1); 1500 ret = btrfs_start_delalloc_inodes(root, 1);
1501 if (ret) {
1502 btrfs_abort_transaction(trans, root, ret);
1503 goto cleanup_transaction;
1504 }
1501 btrfs_wait_ordered_extents(root, 1); 1505 btrfs_wait_ordered_extents(root, 1);
1502 } 1506 }
1503 1507