summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2012-09-20 03:54:00 -0400
committerChris Mason <chris.mason@fusionio.com>2012-10-09 09:15:39 -0400
commit354aa0fb6d5b97b262e056f7ad7bfc88d7ce0004 (patch)
tree3f10ebc7209b412a776250922449bb138c861e15 /fs/btrfs/disk-io.c
parenta698d0755adb6f27289d1e6610b2240595d27e8c (diff)
Btrfs: fix orphan transaction on the freezed filesystem
With the following debug patch: static int btrfs_freeze(struct super_block *sb) { + struct btrfs_fs_info *fs_info = btrfs_sb(sb); + struct btrfs_transaction *trans; + + spin_lock(&fs_info->trans_lock); + trans = fs_info->running_transaction; + if (trans) { + printk("Transid %llu, use_count %d, num_writer %d\n", + trans->transid, atomic_read(&trans->use_count), + atomic_read(&trans->num_writers)); + } + spin_unlock(&fs_info->trans_lock); return 0; } I found there was a orphan transaction after the freeze operation was done. It is because the transaction may not be committed when the transaction handle end even though it is the last handle of the current transaction. This design avoid committing the transaction frequently, but also introduce the above problem. So I add btrfs_attach_transaction() which can catch the current transaction and commit it. If there is no transaction, it will return ENOENT, and do not anything. This function also can be used to instead of btrfs_join_transaction_freeze() because it don't increase the writer counter and don't start a new transaction, so it also can fix the deadlock between sync and freeze. Besides that, it is used to instead of btrfs_join_transaction() in transaction_kthread(), because if there is no transaction, the transaction kthread needn't anything. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 2c18a4eb4d5a..dcaf55695e6f 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) {