diff options
-rw-r--r-- | fs/btrfs/file.c | 12 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 3 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 1 |
3 files changed, 15 insertions, 1 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 030012e1710c..72df63b0c799 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1928,12 +1928,24 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
1928 | if (file->private_data) | 1928 | if (file->private_data) |
1929 | btrfs_ioctl_trans_end(file); | 1929 | btrfs_ioctl_trans_end(file); |
1930 | 1930 | ||
1931 | /* | ||
1932 | * We use start here because we will need to wait on the IO to complete | ||
1933 | * in btrfs_sync_log, which could require joining a transaction (for | ||
1934 | * example checking cross references in the nocow path). If we use join | ||
1935 | * here we could get into a situation where we're waiting on IO to | ||
1936 | * happen that is blocked on a transaction trying to commit. With start | ||
1937 | * we inc the extwriter counter, so we wait for all extwriters to exit | ||
1938 | * before we start blocking join'ers. This comment is to keep somebody | ||
1939 | * from thinking they are super smart and changing this to | ||
1940 | * btrfs_join_transaction *cough*Josef*cough*. | ||
1941 | */ | ||
1931 | trans = btrfs_start_transaction(root, 0); | 1942 | trans = btrfs_start_transaction(root, 0); |
1932 | if (IS_ERR(trans)) { | 1943 | if (IS_ERR(trans)) { |
1933 | ret = PTR_ERR(trans); | 1944 | ret = PTR_ERR(trans); |
1934 | mutex_unlock(&inode->i_mutex); | 1945 | mutex_unlock(&inode->i_mutex); |
1935 | goto out; | 1946 | goto out; |
1936 | } | 1947 | } |
1948 | trans->sync = true; | ||
1937 | 1949 | ||
1938 | ret = btrfs_log_dentry_safe(trans, root, dentry); | 1950 | ret = btrfs_log_dentry_safe(trans, root, dentry); |
1939 | if (ret < 0) { | 1951 | if (ret < 0) { |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index da2ac4c6d78b..b16352ce0f73 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -474,6 +474,7 @@ again: | |||
474 | h->type = type; | 474 | h->type = type; |
475 | h->allocating_chunk = false; | 475 | h->allocating_chunk = false; |
476 | h->reloc_reserved = false; | 476 | h->reloc_reserved = false; |
477 | h->sync = false; | ||
477 | INIT_LIST_HEAD(&h->qgroup_ref_list); | 478 | INIT_LIST_HEAD(&h->qgroup_ref_list); |
478 | INIT_LIST_HEAD(&h->new_bgs); | 479 | INIT_LIST_HEAD(&h->new_bgs); |
479 | 480 | ||
@@ -713,7 +714,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
713 | btrfs_create_pending_block_groups(trans, root); | 714 | btrfs_create_pending_block_groups(trans, root); |
714 | 715 | ||
715 | trans->delayed_ref_updates = 0; | 716 | trans->delayed_ref_updates = 0; |
716 | if (btrfs_should_throttle_delayed_refs(trans, root)) { | 717 | if (!trans->sync && btrfs_should_throttle_delayed_refs(trans, root)) { |
717 | cur = max_t(unsigned long, cur, 1); | 718 | cur = max_t(unsigned long, cur, 1); |
718 | trans->delayed_ref_updates = 0; | 719 | trans->delayed_ref_updates = 0; |
719 | btrfs_run_delayed_refs(trans, root, cur); | 720 | btrfs_run_delayed_refs(trans, root, cur); |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index d05b6013fea8..6ac037e9f9f0 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -93,6 +93,7 @@ struct btrfs_trans_handle { | |||
93 | short adding_csums; | 93 | short adding_csums; |
94 | bool allocating_chunk; | 94 | bool allocating_chunk; |
95 | bool reloc_reserved; | 95 | bool reloc_reserved; |
96 | bool sync; | ||
96 | unsigned int type; | 97 | unsigned int type; |
97 | /* | 98 | /* |
98 | * this root is only needed to validate that the root passed to | 99 | * this root is only needed to validate that the root passed to |