aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c55
1 files changed, 37 insertions, 18 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 82b03afcbd92..1791c6e3d834 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -56,48 +56,49 @@ static noinline void switch_commit_root(struct btrfs_root *root)
56static noinline int join_transaction(struct btrfs_root *root, int nofail) 56static noinline int join_transaction(struct btrfs_root *root, int nofail)
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 60
60 spin_lock(&root->fs_info->trans_lock); 61 spin_lock(&fs_info->trans_lock);
61loop: 62loop:
62 /* The file system has been taken offline. No new transactions. */ 63 /* The file system has been taken offline. No new transactions. */
63 if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { 64 if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
64 spin_unlock(&root->fs_info->trans_lock); 65 spin_unlock(&fs_info->trans_lock);
65 return -EROFS; 66 return -EROFS;
66 } 67 }
67 68
68 if (root->fs_info->trans_no_join) { 69 if (fs_info->trans_no_join) {
69 if (!nofail) { 70 if (!nofail) {
70 spin_unlock(&root->fs_info->trans_lock); 71 spin_unlock(&fs_info->trans_lock);
71 return -EBUSY; 72 return -EBUSY;
72 } 73 }
73 } 74 }
74 75
75 cur_trans = root->fs_info->running_transaction; 76 cur_trans = fs_info->running_transaction;
76 if (cur_trans) { 77 if (cur_trans) {
77 if (cur_trans->aborted) { 78 if (cur_trans->aborted) {
78 spin_unlock(&root->fs_info->trans_lock); 79 spin_unlock(&fs_info->trans_lock);
79 return cur_trans->aborted; 80 return cur_trans->aborted;
80 } 81 }
81 atomic_inc(&cur_trans->use_count); 82 atomic_inc(&cur_trans->use_count);
82 atomic_inc(&cur_trans->num_writers); 83 atomic_inc(&cur_trans->num_writers);
83 cur_trans->num_joined++; 84 cur_trans->num_joined++;
84 spin_unlock(&root->fs_info->trans_lock); 85 spin_unlock(&fs_info->trans_lock);
85 return 0; 86 return 0;
86 } 87 }
87 spin_unlock(&root->fs_info->trans_lock); 88 spin_unlock(&fs_info->trans_lock);
88 89
89 cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS); 90 cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS);
90 if (!cur_trans) 91 if (!cur_trans)
91 return -ENOMEM; 92 return -ENOMEM;
92 93
93 spin_lock(&root->fs_info->trans_lock); 94 spin_lock(&fs_info->trans_lock);
94 if (root->fs_info->running_transaction) { 95 if (fs_info->running_transaction) {
95 /* 96 /*
96 * someone started a transaction after we unlocked. Make sure 97 * someone started a transaction after we unlocked. Make sure
97 * to redo the trans_no_join checks above 98 * to redo the trans_no_join checks above
98 */ 99 */
99 kmem_cache_free(btrfs_transaction_cachep, cur_trans); 100 kmem_cache_free(btrfs_transaction_cachep, cur_trans);
100 cur_trans = root->fs_info->running_transaction; 101 cur_trans = fs_info->running_transaction;
101 goto loop; 102 goto loop;
102 } 103 }
103 104
@@ -122,20 +123,38 @@ loop:
122 cur_trans->delayed_refs.flushing = 0; 123 cur_trans->delayed_refs.flushing = 0;
123 cur_trans->delayed_refs.run_delayed_start = 0; 124 cur_trans->delayed_refs.run_delayed_start = 0;
124 cur_trans->delayed_refs.seq = 1; 125 cur_trans->delayed_refs.seq = 1;
126
127 /*
128 * although the tree mod log is per file system and not per transaction,
129 * the log must never go across transaction boundaries.
130 */
131 smp_mb();
132 if (!list_empty(&fs_info->tree_mod_seq_list)) {
133 printk(KERN_ERR "btrfs: tree_mod_seq_list not empty when "
134 "creating a fresh transaction\n");
135 WARN_ON(1);
136 }
137 if (!RB_EMPTY_ROOT(&fs_info->tree_mod_log)) {
138 printk(KERN_ERR "btrfs: tree_mod_log rb tree not empty when "
139 "creating a fresh transaction\n");
140 WARN_ON(1);
141 }
142 atomic_set(&fs_info->tree_mod_seq, 0);
143
125 init_waitqueue_head(&cur_trans->delayed_refs.seq_wait); 144 init_waitqueue_head(&cur_trans->delayed_refs.seq_wait);
126 spin_lock_init(&cur_trans->commit_lock); 145 spin_lock_init(&cur_trans->commit_lock);
127 spin_lock_init(&cur_trans->delayed_refs.lock); 146 spin_lock_init(&cur_trans->delayed_refs.lock);
128 INIT_LIST_HEAD(&cur_trans->delayed_refs.seq_head); 147 INIT_LIST_HEAD(&cur_trans->delayed_refs.seq_head);
129 148
130 INIT_LIST_HEAD(&cur_trans->pending_snapshots); 149 INIT_LIST_HEAD(&cur_trans->pending_snapshots);
131 list_add_tail(&cur_trans->list, &root->fs_info->trans_list); 150 list_add_tail(&cur_trans->list, &fs_info->trans_list);
132 extent_io_tree_init(&cur_trans->dirty_pages, 151 extent_io_tree_init(&cur_trans->dirty_pages,
133 root->fs_info->btree_inode->i_mapping); 152 fs_info->btree_inode->i_mapping);
134 root->fs_info->generation++; 153 fs_info->generation++;
135 cur_trans->transid = root->fs_info->generation; 154 cur_trans->transid = fs_info->generation;
136 root->fs_info->running_transaction = cur_trans; 155 fs_info->running_transaction = cur_trans;
137 cur_trans->aborted = 0; 156 cur_trans->aborted = 0;
138 spin_unlock(&root->fs_info->trans_lock); 157 spin_unlock(&fs_info->trans_lock);
139 158
140 return 0; 159 return 0;
141} 160}