2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public
4 * License v2 as published by the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * General Public License for more details.
11 * You should have received a copy of the GNU General Public
12 * License along with this program; if not, write to the
13 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14 * Boston, MA 021110-1307, USA.
17 #include "kerncompat.h"
19 #include "transaction.h"
23 struct btrfs_trans_handle
* btrfs_start_transaction(struct btrfs_root
*root
,
26 struct btrfs_fs_info
*fs_info
= root
->fs_info
;
27 struct btrfs_trans_handle
*h
= kzalloc(sizeof(*h
), GFP_NOFS
);
29 if (fs_info
->transaction_aborted
)
30 return ERR_PTR(-EROFS
);
33 return ERR_PTR(-ENOMEM
);
34 if (root
->commit_root
) {
35 error("commit_root aleady set when starting transaction");
37 return ERR_PTR(-EINVAL
);
39 if (fs_info
->running_transaction
) {
40 error("attempt to start transaction over already running one");
42 return ERR_PTR(-EINVAL
);
45 fs_info
->running_transaction
= h
;
46 fs_info
->generation
++;
47 h
->transid
= fs_info
->generation
;
48 h
->blocks_reserved
= num_blocks
;
49 root
->last_trans
= h
->transid
;
50 root
->commit_root
= root
->node
;
51 extent_buffer_get(root
->node
);
56 static int update_cowonly_root(struct btrfs_trans_handle
*trans
,
57 struct btrfs_root
*root
)
61 struct btrfs_root
*tree_root
= root
->fs_info
->tree_root
;
63 btrfs_write_dirty_block_groups(trans
, root
);
65 old_root_bytenr
= btrfs_root_bytenr(&root
->root_item
);
66 if (old_root_bytenr
== root
->node
->start
)
68 btrfs_set_root_bytenr(&root
->root_item
,
70 btrfs_set_root_generation(&root
->root_item
,
72 root
->root_item
.level
= btrfs_header_level(root
->node
);
73 ret
= btrfs_update_root(trans
, tree_root
,
77 btrfs_write_dirty_block_groups(trans
, root
);
82 int commit_tree_roots(struct btrfs_trans_handle
*trans
,
83 struct btrfs_fs_info
*fs_info
)
85 struct btrfs_root
*root
;
86 struct list_head
*next
;
87 struct extent_buffer
*eb
;
90 if (fs_info
->readonly
)
93 eb
= fs_info
->tree_root
->node
;
94 extent_buffer_get(eb
);
95 ret
= btrfs_cow_block(trans
, fs_info
->tree_root
, eb
, NULL
, 0, &eb
);
96 free_extent_buffer(eb
);
100 while(!list_empty(&fs_info
->dirty_cowonly_roots
)) {
101 next
= fs_info
->dirty_cowonly_roots
.next
;
103 root
= list_entry(next
, struct btrfs_root
, dirty_list
);
104 update_cowonly_root(trans
, root
);
105 free_extent_buffer(root
->commit_root
);
106 root
->commit_root
= NULL
;
112 int __commit_transaction(struct btrfs_trans_handle
*trans
,
113 struct btrfs_root
*root
)
117 struct btrfs_fs_info
*fs_info
= root
->fs_info
;
118 struct extent_buffer
*eb
;
119 struct extent_io_tree
*tree
= &fs_info
->extent_cache
;
123 ret
= find_first_extent_bit(tree
, 0, &start
, &end
,
127 while(start
<= end
) {
128 eb
= find_first_extent_buffer(tree
, start
);
129 BUG_ON(!eb
|| eb
->start
!= start
);
130 ret
= write_tree_block(trans
, fs_info
, eb
);
133 clear_extent_buffer_dirty(eb
);
134 free_extent_buffer(eb
);
140 int btrfs_commit_transaction(struct btrfs_trans_handle
*trans
,
141 struct btrfs_root
*root
)
143 u64 transid
= trans
->transid
;
145 struct btrfs_fs_info
*fs_info
= root
->fs_info
;
147 if (trans
->fs_info
->transaction_aborted
)
150 if (root
->commit_root
== root
->node
)
152 if (root
== root
->fs_info
->tree_root
)
154 if (root
== root
->fs_info
->chunk_root
)
157 free_extent_buffer(root
->commit_root
);
158 root
->commit_root
= NULL
;
160 btrfs_set_root_bytenr(&root
->root_item
, root
->node
->start
);
161 btrfs_set_root_generation(&root
->root_item
, trans
->transid
);
162 root
->root_item
.level
= btrfs_header_level(root
->node
);
163 ret
= btrfs_update_root(trans
, root
->fs_info
->tree_root
,
164 &root
->root_key
, &root
->root_item
);
167 ret
= commit_tree_roots(trans
, fs_info
);
169 ret
= __commit_transaction(trans
, root
);
171 write_ctree_super(trans
, fs_info
);
172 btrfs_finish_extent_commit(trans
, fs_info
->extent_root
,
173 &fs_info
->pinned_extents
);
175 free_extent_buffer(root
->commit_root
);
176 root
->commit_root
= NULL
;
177 fs_info
->running_transaction
= NULL
;
178 fs_info
->last_trans_committed
= transid
;
182 void btrfs_abort_transaction(struct btrfs_trans_handle
*trans
, int error
)
184 trans
->fs_info
->transaction_aborted
= error
;