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 h
->reinit_extent_tree
= false;
50 root
->last_trans
= h
->transid
;
51 root
->commit_root
= root
->node
;
52 extent_buffer_get(root
->node
);
57 static int update_cowonly_root(struct btrfs_trans_handle
*trans
,
58 struct btrfs_root
*root
)
62 struct btrfs_root
*tree_root
= root
->fs_info
->tree_root
;
64 btrfs_write_dirty_block_groups(trans
, root
);
66 old_root_bytenr
= btrfs_root_bytenr(&root
->root_item
);
67 if (old_root_bytenr
== root
->node
->start
)
69 btrfs_set_root_bytenr(&root
->root_item
,
71 btrfs_set_root_generation(&root
->root_item
,
73 root
->root_item
.level
= btrfs_header_level(root
->node
);
74 ret
= btrfs_update_root(trans
, tree_root
,
78 btrfs_write_dirty_block_groups(trans
, root
);
83 int commit_tree_roots(struct btrfs_trans_handle
*trans
,
84 struct btrfs_fs_info
*fs_info
)
86 struct btrfs_root
*root
;
87 struct list_head
*next
;
88 struct extent_buffer
*eb
;
91 if (fs_info
->readonly
)
94 eb
= fs_info
->tree_root
->node
;
95 extent_buffer_get(eb
);
96 ret
= btrfs_cow_block(trans
, fs_info
->tree_root
, eb
, NULL
, 0, &eb
);
97 free_extent_buffer(eb
);
101 while(!list_empty(&fs_info
->dirty_cowonly_roots
)) {
102 next
= fs_info
->dirty_cowonly_roots
.next
;
104 root
= list_entry(next
, struct btrfs_root
, dirty_list
);
105 update_cowonly_root(trans
, root
);
106 free_extent_buffer(root
->commit_root
);
107 root
->commit_root
= NULL
;
113 int __commit_transaction(struct btrfs_trans_handle
*trans
,
114 struct btrfs_root
*root
)
118 struct btrfs_fs_info
*fs_info
= root
->fs_info
;
119 struct extent_buffer
*eb
;
120 struct extent_io_tree
*tree
= &fs_info
->extent_cache
;
124 ret
= find_first_extent_bit(tree
, 0, &start
, &end
,
128 while(start
<= end
) {
129 eb
= find_first_extent_buffer(tree
, start
);
130 BUG_ON(!eb
|| eb
->start
!= start
);
131 ret
= write_tree_block(trans
, fs_info
, eb
);
134 clear_extent_buffer_dirty(eb
);
135 free_extent_buffer(eb
);
141 int btrfs_commit_transaction(struct btrfs_trans_handle
*trans
,
142 struct btrfs_root
*root
)
144 u64 transid
= trans
->transid
;
146 struct btrfs_fs_info
*fs_info
= root
->fs_info
;
148 if (trans
->fs_info
->transaction_aborted
)
151 if (root
->commit_root
== root
->node
)
153 if (root
== root
->fs_info
->tree_root
)
155 if (root
== root
->fs_info
->chunk_root
)
158 free_extent_buffer(root
->commit_root
);
159 root
->commit_root
= NULL
;
161 btrfs_set_root_bytenr(&root
->root_item
, root
->node
->start
);
162 btrfs_set_root_generation(&root
->root_item
, trans
->transid
);
163 root
->root_item
.level
= btrfs_header_level(root
->node
);
164 ret
= btrfs_update_root(trans
, root
->fs_info
->tree_root
,
165 &root
->root_key
, &root
->root_item
);
168 ret
= commit_tree_roots(trans
, fs_info
);
170 ret
= __commit_transaction(trans
, root
);
172 write_ctree_super(trans
);
173 btrfs_finish_extent_commit(trans
, fs_info
->extent_root
,
174 &fs_info
->pinned_extents
);
176 free_extent_buffer(root
->commit_root
);
177 root
->commit_root
= NULL
;
178 fs_info
->running_transaction
= NULL
;
179 fs_info
->last_trans_committed
= transid
;
183 void btrfs_abort_transaction(struct btrfs_trans_handle
*trans
, int error
)
185 trans
->fs_info
->transaction_aborted
= error
;