diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-01-08 15:46:30 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:59 -0400 |
commit | e2008b61401ecb467a8ce1788fcd2116ae1cfbc1 (patch) | |
tree | 8f13935108abaca29c894ca1f9309c9813c9e194 | |
parent | 3063d29f2a4d4a4e9fa1ec77c124514f287c6da7 (diff) |
Btrfs: Add some simple throttling to wait for data=ordered and snapshot deletion
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 7 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 1 | ||||
-rw-r--r-- | fs/btrfs/file.c | 1 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 12 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 4 |
6 files changed, 26 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index b55dba58dfaa..f0fb1978553c 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -345,6 +345,7 @@ struct btrfs_fs_info { | |||
345 | struct completion kobj_unregister; | 345 | struct completion kobj_unregister; |
346 | int do_barriers; | 346 | int do_barriers; |
347 | int closing; | 347 | int closing; |
348 | unsigned long throttles; | ||
348 | 349 | ||
349 | u64 total_pinned; | 350 | u64 total_pinned; |
350 | spinlock_t delalloc_lock; | 351 | spinlock_t delalloc_lock; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 34cf1f1f47be..e0940a39ff07 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -631,6 +631,7 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
631 | fs_info->tree_root = tree_root; | 631 | fs_info->tree_root = tree_root; |
632 | fs_info->extent_root = extent_root; | 632 | fs_info->extent_root = extent_root; |
633 | fs_info->sb = sb; | 633 | fs_info->sb = sb; |
634 | fs_info->throttles = 0; | ||
634 | fs_info->mount_opt = 0; | 635 | fs_info->mount_opt = 0; |
635 | fs_info->max_extent = (u64)-1; | 636 | fs_info->max_extent = (u64)-1; |
636 | fs_info->delalloc_bytes = 0; | 637 | fs_info->delalloc_bytes = 0; |
@@ -889,6 +890,12 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf) | |||
889 | set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf); | 890 | set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf); |
890 | } | 891 | } |
891 | 892 | ||
893 | void btrfs_throttle(struct btrfs_root *root) | ||
894 | { | ||
895 | if (root->fs_info->throttles) | ||
896 | congestion_wait(WRITE, HZ/10); | ||
897 | } | ||
898 | |||
892 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) | 899 | void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) |
893 | { | 900 | { |
894 | balance_dirty_pages_ratelimited_nr( | 901 | balance_dirty_pages_ratelimited_nr( |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index dae9fba8efcd..828f3a2081b6 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -64,4 +64,5 @@ int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf); | |||
64 | int btrfs_read_buffer(struct extent_buffer *buf); | 64 | int btrfs_read_buffer(struct extent_buffer *buf); |
65 | u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len); | 65 | u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len); |
66 | void btrfs_csum_final(u32 crc, char *result); | 66 | void btrfs_csum_final(u32 crc, char *result); |
67 | void btrfs_throttle(struct btrfs_root *root); | ||
67 | #endif | 68 | #endif |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 0a5f4defe59b..897242e87fa7 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -800,6 +800,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
800 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, num_pages); | 800 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, num_pages); |
801 | if (num_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1) | 801 | if (num_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1) |
802 | btrfs_btree_balance_dirty(root, 1); | 802 | btrfs_btree_balance_dirty(root, 1); |
803 | btrfs_throttle(root); | ||
803 | cond_resched(); | 804 | cond_resched(); |
804 | } | 805 | } |
805 | out: | 806 | out: |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 10cece11dbd8..2cb2dd32407e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -610,6 +610,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
610 | fail: | 610 | fail: |
611 | mutex_unlock(&root->fs_info->fs_mutex); | 611 | mutex_unlock(&root->fs_info->fs_mutex); |
612 | btrfs_btree_balance_dirty(root, nr); | 612 | btrfs_btree_balance_dirty(root, nr); |
613 | btrfs_throttle(root); | ||
613 | return ret; | 614 | return ret; |
614 | } | 615 | } |
615 | 616 | ||
@@ -644,6 +645,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
644 | fail: | 645 | fail: |
645 | mutex_unlock(&root->fs_info->fs_mutex); | 646 | mutex_unlock(&root->fs_info->fs_mutex); |
646 | btrfs_btree_balance_dirty(root, nr); | 647 | btrfs_btree_balance_dirty(root, nr); |
648 | btrfs_throttle(root); | ||
647 | 649 | ||
648 | if (ret && !err) | 650 | if (ret && !err) |
649 | err = ret; | 651 | err = ret; |
@@ -1010,6 +1012,7 @@ void btrfs_delete_inode(struct inode *inode) | |||
1010 | btrfs_end_transaction(trans, root); | 1012 | btrfs_end_transaction(trans, root); |
1011 | mutex_unlock(&root->fs_info->fs_mutex); | 1013 | mutex_unlock(&root->fs_info->fs_mutex); |
1012 | btrfs_btree_balance_dirty(root, nr); | 1014 | btrfs_btree_balance_dirty(root, nr); |
1015 | btrfs_throttle(root); | ||
1013 | return; | 1016 | return; |
1014 | 1017 | ||
1015 | no_delete_lock: | 1018 | no_delete_lock: |
@@ -1017,6 +1020,7 @@ no_delete_lock: | |||
1017 | btrfs_end_transaction(trans, root); | 1020 | btrfs_end_transaction(trans, root); |
1018 | mutex_unlock(&root->fs_info->fs_mutex); | 1021 | mutex_unlock(&root->fs_info->fs_mutex); |
1019 | btrfs_btree_balance_dirty(root, nr); | 1022 | btrfs_btree_balance_dirty(root, nr); |
1023 | btrfs_throttle(root); | ||
1020 | no_delete: | 1024 | no_delete: |
1021 | clear_inode(inode); | 1025 | clear_inode(inode); |
1022 | } | 1026 | } |
@@ -1574,6 +1578,7 @@ fail: | |||
1574 | iput(inode); | 1578 | iput(inode); |
1575 | } | 1579 | } |
1576 | btrfs_btree_balance_dirty(root, nr); | 1580 | btrfs_btree_balance_dirty(root, nr); |
1581 | btrfs_throttle(root); | ||
1577 | return err; | 1582 | return err; |
1578 | } | 1583 | } |
1579 | 1584 | ||
@@ -1633,6 +1638,7 @@ fail: | |||
1633 | iput(inode); | 1638 | iput(inode); |
1634 | } | 1639 | } |
1635 | btrfs_btree_balance_dirty(root, nr); | 1640 | btrfs_btree_balance_dirty(root, nr); |
1641 | btrfs_throttle(root); | ||
1636 | return err; | 1642 | return err; |
1637 | } | 1643 | } |
1638 | 1644 | ||
@@ -1684,6 +1690,7 @@ fail: | |||
1684 | iput(inode); | 1690 | iput(inode); |
1685 | } | 1691 | } |
1686 | btrfs_btree_balance_dirty(root, nr); | 1692 | btrfs_btree_balance_dirty(root, nr); |
1693 | btrfs_throttle(root); | ||
1687 | return err; | 1694 | return err; |
1688 | } | 1695 | } |
1689 | 1696 | ||
@@ -1752,6 +1759,7 @@ out_unlock: | |||
1752 | if (drop_on_err) | 1759 | if (drop_on_err) |
1753 | iput(inode); | 1760 | iput(inode); |
1754 | btrfs_btree_balance_dirty(root, nr); | 1761 | btrfs_btree_balance_dirty(root, nr); |
1762 | btrfs_throttle(root); | ||
1755 | return err; | 1763 | return err; |
1756 | } | 1764 | } |
1757 | 1765 | ||
@@ -2117,6 +2125,7 @@ static void btrfs_truncate(struct inode *inode) | |||
2117 | BUG_ON(ret); | 2125 | BUG_ON(ret); |
2118 | mutex_unlock(&root->fs_info->fs_mutex); | 2126 | mutex_unlock(&root->fs_info->fs_mutex); |
2119 | btrfs_btree_balance_dirty(root, nr); | 2127 | btrfs_btree_balance_dirty(root, nr); |
2128 | btrfs_throttle(root); | ||
2120 | } | 2129 | } |
2121 | 2130 | ||
2122 | static int noinline create_subvol(struct btrfs_root *root, char *name, | 2131 | static int noinline create_subvol(struct btrfs_root *root, char *name, |
@@ -2245,6 +2254,7 @@ fail: | |||
2245 | fail_commit: | 2254 | fail_commit: |
2246 | mutex_unlock(&root->fs_info->fs_mutex); | 2255 | mutex_unlock(&root->fs_info->fs_mutex); |
2247 | btrfs_btree_balance_dirty(root, nr); | 2256 | btrfs_btree_balance_dirty(root, nr); |
2257 | btrfs_throttle(root); | ||
2248 | return ret; | 2258 | return ret; |
2249 | } | 2259 | } |
2250 | 2260 | ||
@@ -2287,6 +2297,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
2287 | fail_unlock: | 2297 | fail_unlock: |
2288 | mutex_unlock(&root->fs_info->fs_mutex); | 2298 | mutex_unlock(&root->fs_info->fs_mutex); |
2289 | btrfs_btree_balance_dirty(root, nr); | 2299 | btrfs_btree_balance_dirty(root, nr); |
2300 | btrfs_throttle(root); | ||
2290 | return ret; | 2301 | return ret; |
2291 | } | 2302 | } |
2292 | 2303 | ||
@@ -2827,6 +2838,7 @@ out_fail: | |||
2827 | iput(inode); | 2838 | iput(inode); |
2828 | } | 2839 | } |
2829 | btrfs_btree_balance_dirty(root, nr); | 2840 | btrfs_btree_balance_dirty(root, nr); |
2841 | btrfs_throttle(root); | ||
2830 | return err; | 2842 | return err; |
2831 | } | 2843 | } |
2832 | 2844 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index dc9865323e38..614903f5c884 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -424,6 +424,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root, | |||
424 | 424 | ||
425 | num_bytes = btrfs_root_used(&dirty->root->root_item); | 425 | num_bytes = btrfs_root_used(&dirty->root->root_item); |
426 | root = dirty->latest_root; | 426 | root = dirty->latest_root; |
427 | root->fs_info->throttles++; | ||
427 | 428 | ||
428 | while(1) { | 429 | while(1) { |
429 | trans = btrfs_start_transaction(tree_root, 1); | 430 | trans = btrfs_start_transaction(tree_root, 1); |
@@ -447,6 +448,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root, | |||
447 | mutex_lock(&tree_root->fs_info->fs_mutex); | 448 | mutex_lock(&tree_root->fs_info->fs_mutex); |
448 | } | 449 | } |
449 | BUG_ON(ret); | 450 | BUG_ON(ret); |
451 | root->fs_info->throttles--; | ||
450 | 452 | ||
451 | num_bytes -= btrfs_root_used(&dirty->root->root_item); | 453 | num_bytes -= btrfs_root_used(&dirty->root->root_item); |
452 | bytes_used = btrfs_root_used(&root->root_item); | 454 | bytes_used = btrfs_root_used(&root->root_item); |
@@ -484,6 +486,7 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, | |||
484 | u64 objectid = 0; | 486 | u64 objectid = 0; |
485 | int ret; | 487 | int ret; |
486 | 488 | ||
489 | root->fs_info->throttles++; | ||
487 | while(1) { | 490 | while(1) { |
488 | ret = btrfs_find_first_ordered_inode( | 491 | ret = btrfs_find_first_ordered_inode( |
489 | &cur_trans->ordered_inode_tree, | 492 | &cur_trans->ordered_inode_tree, |
@@ -523,6 +526,7 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, | |||
523 | mutex_lock(&root->fs_info->fs_mutex); | 526 | mutex_lock(&root->fs_info->fs_mutex); |
524 | mutex_lock(&root->fs_info->trans_mutex); | 527 | mutex_lock(&root->fs_info->trans_mutex); |
525 | } | 528 | } |
529 | root->fs_info->throttles--; | ||
526 | return 0; | 530 | return 0; |
527 | } | 531 | } |
528 | 532 | ||