aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/extent-tree.c3
-rw-r--r--fs/btrfs/inode.c18
-rw-r--r--fs/btrfs/transaction.c62
-rw-r--r--fs/btrfs/transaction.h5
4 files changed, 80 insertions, 8 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 3b8b6c212701..a421c32c6cfe 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3797,7 +3797,8 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
3797 break; 3797 break;
3798 if (wret < 0) 3798 if (wret < 0)
3799 ret = wret; 3799 ret = wret;
3800 if (trans->transaction->in_commit) { 3800 if (trans->transaction->in_commit ||
3801 trans->transaction->delayed_refs.flushing) {
3801 ret = -EAGAIN; 3802 ret = -EAGAIN;
3802 break; 3803 break;
3803 } 3804 }
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 7d4f948bc22a..13a17477c4f4 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1502,6 +1502,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
1502 struct btrfs_trans_handle *trans; 1502 struct btrfs_trans_handle *trans;
1503 struct btrfs_ordered_extent *ordered_extent; 1503 struct btrfs_ordered_extent *ordered_extent;
1504 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; 1504 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
1505 struct btrfs_path *path;
1505 int compressed = 0; 1506 int compressed = 0;
1506 int ret; 1507 int ret;
1507 1508
@@ -1509,6 +1510,23 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
1509 if (!ret) 1510 if (!ret)
1510 return 0; 1511 return 0;
1511 1512
1513 /*
1514 * before we join the transaction, try to do some of our IO.
1515 * This will limit the amount of IO that we have to do with
1516 * the transaction running. We're unlikely to need to do any
1517 * IO if the file extents are new, the disk_i_size checks
1518 * covers the most common case.
1519 */
1520 if (start < BTRFS_I(inode)->disk_i_size) {
1521 path = btrfs_alloc_path();
1522 if (path) {
1523 ret = btrfs_lookup_file_extent(NULL, root, path,
1524 inode->i_ino,
1525 start, 0);
1526 btrfs_free_path(path);
1527 }
1528 }
1529
1512 trans = btrfs_join_transaction(root, 1); 1530 trans = btrfs_join_transaction(root, 1);
1513 1531
1514 ordered_extent = btrfs_lookup_ordered_extent(inode, start); 1532 ordered_extent = btrfs_lookup_ordered_extent(inode, start);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 903edab3659a..01c9620bb001 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -192,6 +192,7 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
192 h->alloc_exclude_nr = 0; 192 h->alloc_exclude_nr = 0;
193 h->alloc_exclude_start = 0; 193 h->alloc_exclude_start = 0;
194 h->delayed_ref_updates = 0; 194 h->delayed_ref_updates = 0;
195
195 root->fs_info->running_transaction->use_count++; 196 root->fs_info->running_transaction->use_count++;
196 mutex_unlock(&root->fs_info->trans_mutex); 197 mutex_unlock(&root->fs_info->trans_mutex);
197 return h; 198 return h;
@@ -281,7 +282,6 @@ void btrfs_throttle(struct btrfs_root *root)
281 if (!root->fs_info->open_ioctl_trans) 282 if (!root->fs_info->open_ioctl_trans)
282 wait_current_trans(root); 283 wait_current_trans(root);
283 mutex_unlock(&root->fs_info->trans_mutex); 284 mutex_unlock(&root->fs_info->trans_mutex);
284
285 throttle_on_drops(root); 285 throttle_on_drops(root);
286} 286}
287 287
@@ -298,6 +298,13 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
298 if (cur && 298 if (cur &&
299 trans->transaction->delayed_refs.num_heads_ready > 64) { 299 trans->transaction->delayed_refs.num_heads_ready > 64) {
300 trans->delayed_ref_updates = 0; 300 trans->delayed_ref_updates = 0;
301
302 /*
303 * do a full flush if the transaction is trying
304 * to close
305 */
306 if (trans->transaction->delayed_refs.flushing)
307 cur = 0;
301 btrfs_run_delayed_refs(trans, root, cur); 308 btrfs_run_delayed_refs(trans, root, cur);
302 } else { 309 } else {
303 break; 310 break;
@@ -666,6 +673,31 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
666} 673}
667 674
668/* 675/*
676 * when dropping snapshots, we generate a ton of delayed refs, and it makes
677 * sense not to join the transaction while it is trying to flush the current
678 * queue of delayed refs out.
679 *
680 * This is used by the drop snapshot code only
681 */
682static noinline int wait_transaction_pre_flush(struct btrfs_fs_info *info)
683{
684 DEFINE_WAIT(wait);
685
686 mutex_lock(&info->trans_mutex);
687 while (info->running_transaction &&
688 info->running_transaction->delayed_refs.flushing) {
689 prepare_to_wait(&info->transaction_wait, &wait,
690 TASK_UNINTERRUPTIBLE);
691 mutex_unlock(&info->trans_mutex);
692 schedule();
693 mutex_lock(&info->trans_mutex);
694 finish_wait(&info->transaction_wait, &wait);
695 }
696 mutex_unlock(&info->trans_mutex);
697 return 0;
698}
699
700/*
669 * Given a list of roots that need to be deleted, call btrfs_drop_snapshot on 701 * Given a list of roots that need to be deleted, call btrfs_drop_snapshot on
670 * all of them 702 * all of them
671 */ 703 */
@@ -692,7 +724,22 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
692 atomic_inc(&root->fs_info->throttles); 724 atomic_inc(&root->fs_info->throttles);
693 725
694 while (1) { 726 while (1) {
727 /*
728 * we don't want to jump in and create a bunch of
729 * delayed refs if the transaction is starting to close
730 */
731 wait_transaction_pre_flush(tree_root->fs_info);
695 trans = btrfs_start_transaction(tree_root, 1); 732 trans = btrfs_start_transaction(tree_root, 1);
733
734 /*
735 * we've joined a transaction, make sure it isn't
736 * closing right now
737 */
738 if (trans->transaction->delayed_refs.flushing) {
739 btrfs_end_transaction(trans, tree_root);
740 continue;
741 }
742
696 mutex_lock(&root->fs_info->drop_mutex); 743 mutex_lock(&root->fs_info->drop_mutex);
697 ret = btrfs_drop_snapshot(trans, dirty->root); 744 ret = btrfs_drop_snapshot(trans, dirty->root);
698 if (ret != -EAGAIN) 745 if (ret != -EAGAIN)
@@ -932,20 +979,20 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
932 ret = btrfs_run_delayed_refs(trans, root, 0); 979 ret = btrfs_run_delayed_refs(trans, root, 0);
933 BUG_ON(ret); 980 BUG_ON(ret);
934 981
982 cur_trans = trans->transaction;
935 /* 983 /*
936 * set the flushing flag so procs in this transaction have to 984 * set the flushing flag so procs in this transaction have to
937 * start sending their work down. 985 * start sending their work down.
938 */ 986 */
939 trans->transaction->delayed_refs.flushing = 1; 987 cur_trans->delayed_refs.flushing = 1;
940 988
941 ret = btrfs_run_delayed_refs(trans, root, 0); 989 ret = btrfs_run_delayed_refs(trans, root, 0);
942 BUG_ON(ret); 990 BUG_ON(ret);
943 991
944 INIT_LIST_HEAD(&dirty_fs_roots);
945 mutex_lock(&root->fs_info->trans_mutex); 992 mutex_lock(&root->fs_info->trans_mutex);
946 if (trans->transaction->in_commit) { 993 INIT_LIST_HEAD(&dirty_fs_roots);
947 cur_trans = trans->transaction; 994 if (cur_trans->in_commit) {
948 trans->transaction->use_count++; 995 cur_trans->use_count++;
949 mutex_unlock(&root->fs_info->trans_mutex); 996 mutex_unlock(&root->fs_info->trans_mutex);
950 btrfs_end_transaction(trans, root); 997 btrfs_end_transaction(trans, root);
951 998
@@ -968,7 +1015,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
968 1015
969 trans->transaction->in_commit = 1; 1016 trans->transaction->in_commit = 1;
970 trans->transaction->blocked = 1; 1017 trans->transaction->blocked = 1;
971 cur_trans = trans->transaction;
972 if (cur_trans->list.prev != &root->fs_info->trans_list) { 1018 if (cur_trans->list.prev != &root->fs_info->trans_list) {
973 prev_trans = list_entry(cur_trans->list.prev, 1019 prev_trans = list_entry(cur_trans->list.prev,
974 struct btrfs_transaction, list); 1020 struct btrfs_transaction, list);
@@ -1081,6 +1127,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1081 btrfs_copy_pinned(root, pinned_copy); 1127 btrfs_copy_pinned(root, pinned_copy);
1082 1128
1083 trans->transaction->blocked = 0; 1129 trans->transaction->blocked = 0;
1130
1084 wake_up(&root->fs_info->transaction_throttle); 1131 wake_up(&root->fs_info->transaction_throttle);
1085 wake_up(&root->fs_info->transaction_wait); 1132 wake_up(&root->fs_info->transaction_wait);
1086 1133
@@ -1107,6 +1154,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1107 mutex_lock(&root->fs_info->trans_mutex); 1154 mutex_lock(&root->fs_info->trans_mutex);
1108 1155
1109 cur_trans->commit_done = 1; 1156 cur_trans->commit_done = 1;
1157
1110 root->fs_info->last_trans_committed = cur_trans->transid; 1158 root->fs_info->last_trans_committed = cur_trans->transid;
1111 wake_up(&cur_trans->commit_wait); 1159 wake_up(&cur_trans->commit_wait);
1112 1160
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 94876709217f..94f5bde2b58d 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -23,7 +23,12 @@
23 23
24struct btrfs_transaction { 24struct btrfs_transaction {
25 u64 transid; 25 u64 transid;
26 /*
27 * total writers in this transaction, it must be zero before the
28 * transaction can end
29 */
26 unsigned long num_writers; 30 unsigned long num_writers;
31
27 unsigned long num_joined; 32 unsigned long num_joined;
28 int in_commit; 33 int in_commit;
29 int use_count; 34 int use_count;