aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-03-04 04:44:29 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-03-04 16:33:22 -0500
commitaec8030a8745221c8658f2033b22c98528897b13 (patch)
tree58634fad399097dbde3d4969e498cb913a48aa96 /fs/btrfs/disk-io.c
parent9bf7a4890518186238d2579be16ecc5190a707c0 (diff)
Btrfs: fix wrong handle at error path of create_snapshot() when the commit fails
There are several bugs at error path of create_snapshot() when the transaction commitment failed. - access the freed transaction handler. At the end of the transaction commitment, the transaction handler was freed, so we should not access it after the transaction commitment. - we were not aware of the error which happened during the snapshot creation if we submitted a async transaction commitment. - pending snapshot access vs pending snapshot free. when something wrong happened after we submitted a async transaction commitment, the transaction committer would cleanup the pending snapshots and free them. But the snapshot creators were not aware of it, they would access the freed pending snapshots. This patch fixes the above problems by: - remove the dangerous code that accessed the freed handler - assign ->error if the error happens during the snapshot creation - the transaction committer doesn't free the pending snapshots, just assigns the error number and evicts them before we unblock the transaction. Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 02369a3c162e..7d84651e850b 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -62,7 +62,7 @@ static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t,
62static void btrfs_destroy_ordered_extents(struct btrfs_root *root); 62static void btrfs_destroy_ordered_extents(struct btrfs_root *root);
63static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, 63static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
64 struct btrfs_root *root); 64 struct btrfs_root *root);
65static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t); 65static void btrfs_evict_pending_snapshots(struct btrfs_transaction *t);
66static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root); 66static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root);
67static int btrfs_destroy_marked_extents(struct btrfs_root *root, 67static int btrfs_destroy_marked_extents(struct btrfs_root *root,
68 struct extent_io_tree *dirty_pages, 68 struct extent_io_tree *dirty_pages,
@@ -3687,7 +3687,7 @@ int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
3687 return ret; 3687 return ret;
3688} 3688}
3689 3689
3690static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t) 3690static void btrfs_evict_pending_snapshots(struct btrfs_transaction *t)
3691{ 3691{
3692 struct btrfs_pending_snapshot *snapshot; 3692 struct btrfs_pending_snapshot *snapshot;
3693 struct list_head splice; 3693 struct list_head splice;
@@ -3700,10 +3700,8 @@ static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t)
3700 snapshot = list_entry(splice.next, 3700 snapshot = list_entry(splice.next,
3701 struct btrfs_pending_snapshot, 3701 struct btrfs_pending_snapshot,
3702 list); 3702 list);
3703 3703 snapshot->error = -ECANCELED;
3704 list_del_init(&snapshot->list); 3704 list_del_init(&snapshot->list);
3705
3706 kfree(snapshot);
3707 } 3705 }
3708} 3706}
3709 3707
@@ -3840,6 +3838,8 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
3840 cur_trans->blocked = 1; 3838 cur_trans->blocked = 1;
3841 wake_up(&root->fs_info->transaction_blocked_wait); 3839 wake_up(&root->fs_info->transaction_blocked_wait);
3842 3840
3841 btrfs_evict_pending_snapshots(cur_trans);
3842
3843 cur_trans->blocked = 0; 3843 cur_trans->blocked = 0;
3844 wake_up(&root->fs_info->transaction_wait); 3844 wake_up(&root->fs_info->transaction_wait);
3845 3845
@@ -3849,8 +3849,6 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
3849 btrfs_destroy_delayed_inodes(root); 3849 btrfs_destroy_delayed_inodes(root);
3850 btrfs_assert_delayed_root_empty(root); 3850 btrfs_assert_delayed_root_empty(root);
3851 3851
3852 btrfs_destroy_pending_snapshots(cur_trans);
3853
3854 btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages, 3852 btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages,
3855 EXTENT_DIRTY); 3853 EXTENT_DIRTY);
3856 btrfs_destroy_pinned_extent(root, 3854 btrfs_destroy_pinned_extent(root,
@@ -3894,6 +3892,8 @@ int btrfs_cleanup_transaction(struct btrfs_root *root)
3894 if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) 3892 if (waitqueue_active(&root->fs_info->transaction_blocked_wait))
3895 wake_up(&root->fs_info->transaction_blocked_wait); 3893 wake_up(&root->fs_info->transaction_blocked_wait);
3896 3894
3895 btrfs_evict_pending_snapshots(t);
3896
3897 t->blocked = 0; 3897 t->blocked = 0;
3898 smp_mb(); 3898 smp_mb();
3899 if (waitqueue_active(&root->fs_info->transaction_wait)) 3899 if (waitqueue_active(&root->fs_info->transaction_wait))
@@ -3907,8 +3907,6 @@ int btrfs_cleanup_transaction(struct btrfs_root *root)
3907 btrfs_destroy_delayed_inodes(root); 3907 btrfs_destroy_delayed_inodes(root);
3908 btrfs_assert_delayed_root_empty(root); 3908 btrfs_assert_delayed_root_empty(root);
3909 3909
3910 btrfs_destroy_pending_snapshots(t);
3911
3912 btrfs_destroy_delalloc_inodes(root); 3910 btrfs_destroy_delalloc_inodes(root);
3913 3911
3914 spin_lock(&root->fs_info->trans_lock); 3912 spin_lock(&root->fs_info->trans_lock);