aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/disk-io.c5
-rw-r--r--fs/btrfs/super.c18
-rw-r--r--fs/btrfs/transaction.c45
-rw-r--r--fs/btrfs/transaction.h4
4 files changed, 49 insertions, 23 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 2c18a4eb4d5..dcaf55695e6 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1657,9 +1657,10 @@ static int transaction_kthread(void *arg)
1657 spin_unlock(&root->fs_info->trans_lock); 1657 spin_unlock(&root->fs_info->trans_lock);
1658 1658
1659 /* If the file system is aborted, this will always fail. */ 1659 /* If the file system is aborted, this will always fail. */
1660 trans = btrfs_join_transaction(root); 1660 trans = btrfs_attach_transaction(root);
1661 if (IS_ERR(trans)) { 1661 if (IS_ERR(trans)) {
1662 cannot_commit = true; 1662 if (PTR_ERR(trans) != -ENOENT)
1663 cannot_commit = true;
1663 goto sleep; 1664 goto sleep;
1664 } 1665 }
1665 if (transid == trans->transid) { 1666 if (transid == trans->transid) {
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index fb260bbf59c..f8b803f30ed 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -854,10 +854,10 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
854 854
855 btrfs_wait_ordered_extents(root, 0); 855 btrfs_wait_ordered_extents(root, 0);
856 856
857 trans = btrfs_join_transaction_freeze(root); 857 trans = btrfs_attach_transaction(root);
858 if (IS_ERR(trans)) { 858 if (IS_ERR(trans)) {
859 /* Frozen, don't bother */ 859 /* no transaction, don't bother */
860 if (PTR_ERR(trans) == -EPERM) 860 if (PTR_ERR(trans) == -ENOENT)
861 return 0; 861 return 0;
862 return PTR_ERR(trans); 862 return PTR_ERR(trans);
863 } 863 }
@@ -1511,7 +1511,17 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
1511 1511
1512static int btrfs_freeze(struct super_block *sb) 1512static int btrfs_freeze(struct super_block *sb)
1513{ 1513{
1514 return 0; 1514 struct btrfs_trans_handle *trans;
1515 struct btrfs_root *root = btrfs_sb(sb)->tree_root;
1516
1517 trans = btrfs_attach_transaction(root);
1518 if (IS_ERR(trans)) {
1519 /* no transaction, don't bother */
1520 if (PTR_ERR(trans) == -ENOENT)
1521 return 0;
1522 return PTR_ERR(trans);
1523 }
1524 return btrfs_commit_transaction(trans, root);
1515} 1525}
1516 1526
1517static int btrfs_unfreeze(struct super_block *sb) 1527static int btrfs_unfreeze(struct super_block *sb)
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index d0a2b7e4938..69139a356f7 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -53,7 +53,7 @@ static noinline void switch_commit_root(struct btrfs_root *root)
53/* 53/*
54 * either allocate a new transaction or hop into the existing one 54 * either allocate a new transaction or hop into the existing one
55 */ 55 */
56static noinline int join_transaction(struct btrfs_root *root, int nofail) 56static noinline int join_transaction(struct btrfs_root *root, int type)
57{ 57{
58 struct btrfs_transaction *cur_trans; 58 struct btrfs_transaction *cur_trans;
59 struct btrfs_fs_info *fs_info = root->fs_info; 59 struct btrfs_fs_info *fs_info = root->fs_info;
@@ -67,7 +67,13 @@ loop:
67 } 67 }
68 68
69 if (fs_info->trans_no_join) { 69 if (fs_info->trans_no_join) {
70 if (!nofail) { 70 /*
71 * If we are JOIN_NOLOCK we're already committing a current
72 * transaction, we just need a handle to deal with something
73 * when committing the transaction, such as inode cache and
74 * space cache. It is a special case.
75 */
76 if (type != TRANS_JOIN_NOLOCK) {
71 spin_unlock(&fs_info->trans_lock); 77 spin_unlock(&fs_info->trans_lock);
72 return -EBUSY; 78 return -EBUSY;
73 } 79 }
@@ -87,6 +93,13 @@ loop:
87 } 93 }
88 spin_unlock(&fs_info->trans_lock); 94 spin_unlock(&fs_info->trans_lock);
89 95
96 /*
97 * If we are ATTACH, we just want to catch the current transaction,
98 * and commit it. If there is no transaction, just return ENOENT.
99 */
100 if (type == TRANS_ATTACH)
101 return -ENOENT;
102
90 cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS); 103 cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS);
91 if (!cur_trans) 104 if (!cur_trans)
92 return -ENOMEM; 105 return -ENOMEM;
@@ -340,27 +353,28 @@ again:
340 * because we're already holding a ref. We need this because we could 353 * because we're already holding a ref. We need this because we could
341 * have raced in and did an fsync() on a file which can kick a commit 354 * have raced in and did an fsync() on a file which can kick a commit
342 * and then we deadlock with somebody doing a freeze. 355 * and then we deadlock with somebody doing a freeze.
356 *
357 * If we are ATTACH, it means we just want to catch the current
358 * transaction and commit it, so we needn't do sb_start_intwrite().
343 */ 359 */
344 if (type != TRANS_JOIN_NOLOCK && 360 if (type < TRANS_JOIN_NOLOCK)
345 !__sb_start_write(root->fs_info->sb, SB_FREEZE_FS, false)) {
346 if (type == TRANS_JOIN_FREEZE) {
347 kmem_cache_free(btrfs_trans_handle_cachep, h);
348 return ERR_PTR(-EPERM);
349 }
350 sb_start_intwrite(root->fs_info->sb); 361 sb_start_intwrite(root->fs_info->sb);
351 }
352 362
353 if (may_wait_transaction(root, type)) 363 if (may_wait_transaction(root, type))
354 wait_current_trans(root); 364 wait_current_trans(root);
355 365
356 do { 366 do {
357 ret = join_transaction(root, type == TRANS_JOIN_NOLOCK); 367 ret = join_transaction(root, type);
358 if (ret == -EBUSY) 368 if (ret == -EBUSY)
359 wait_current_trans(root); 369 wait_current_trans(root);
360 } while (ret == -EBUSY); 370 } while (ret == -EBUSY);
361 371
362 if (ret < 0) { 372 if (ret < 0) {
363 sb_end_intwrite(root->fs_info->sb); 373 /* We must get the transaction if we are JOIN_NOLOCK. */
374 BUG_ON(type == TRANS_JOIN_NOLOCK);
375
376 if (type < TRANS_JOIN_NOLOCK)
377 sb_end_intwrite(root->fs_info->sb);
364 kmem_cache_free(btrfs_trans_handle_cachep, h); 378 kmem_cache_free(btrfs_trans_handle_cachep, h);
365 return ERR_PTR(ret); 379 return ERR_PTR(ret);
366 } 380 }
@@ -432,9 +446,9 @@ struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root
432 return start_transaction(root, 0, TRANS_USERSPACE, 0); 446 return start_transaction(root, 0, TRANS_USERSPACE, 0);
433} 447}
434 448
435struct btrfs_trans_handle *btrfs_join_transaction_freeze(struct btrfs_root *root) 449struct btrfs_trans_handle *btrfs_attach_transaction(struct btrfs_root *root)
436{ 450{
437 return start_transaction(root, 0, TRANS_JOIN_FREEZE, 0); 451 return start_transaction(root, 0, TRANS_ATTACH, 0);
438} 452}
439 453
440/* wait for a transaction commit to be fully complete */ 454/* wait for a transaction commit to be fully complete */
@@ -605,7 +619,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
605 } 619 }
606 } 620 }
607 621
608 if (lock) 622 if (trans->type < TRANS_JOIN_NOLOCK)
609 sb_end_intwrite(root->fs_info->sb); 623 sb_end_intwrite(root->fs_info->sb);
610 624
611 WARN_ON(cur_trans != info->running_transaction); 625 WARN_ON(cur_trans != info->running_transaction);
@@ -1678,7 +1692,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1678 put_transaction(cur_trans); 1692 put_transaction(cur_trans);
1679 put_transaction(cur_trans); 1693 put_transaction(cur_trans);
1680 1694
1681 sb_end_intwrite(root->fs_info->sb); 1695 if (trans->type < TRANS_JOIN_NOLOCK)
1696 sb_end_intwrite(root->fs_info->sb);
1682 1697
1683 trace_btrfs_transaction_commit(root); 1698 trace_btrfs_transaction_commit(root);
1684 1699
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 0630bd19396..80961947a6b 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -52,7 +52,7 @@ enum btrfs_trans_type {
52 TRANS_JOIN, 52 TRANS_JOIN,
53 TRANS_USERSPACE, 53 TRANS_USERSPACE,
54 TRANS_JOIN_NOLOCK, 54 TRANS_JOIN_NOLOCK,
55 TRANS_JOIN_FREEZE, 55 TRANS_ATTACH,
56}; 56};
57 57
58struct btrfs_trans_handle { 58struct btrfs_trans_handle {
@@ -109,7 +109,7 @@ struct btrfs_trans_handle *btrfs_start_transaction_noflush(
109 struct btrfs_root *root, int num_items); 109 struct btrfs_root *root, int num_items);
110struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root); 110struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root);
111struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root); 111struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root);
112struct btrfs_trans_handle *btrfs_join_transaction_freeze(struct btrfs_root *root); 112struct btrfs_trans_handle *btrfs_attach_transaction(struct btrfs_root *root);
113struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root); 113struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *root);
114int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid); 114int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid);
115int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, 115int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,